1CS 211 Midterm Study Guide In preparing for your test, you should be aware that anything in the required readings, anything presented in lecture, and anything covered in the labs and assignments, is valid testing material. This guide does not attempt to go into complete detail, especially when that detail is available already in the slides and in the book. Throughout the slides, there are many "Practice Problems" slides; they are an excellent starting point for the sorts of sample problems you might expect to see on the exam. Other examples (not explicitly listed as practice problems) in the slides are also quite instructive of what to expect on the test. Format will be part multiple choice, part short answer, part coding. Java Basics The Java compiler translates from source code to bytecode, which runs on the "Java Virtual Machine". Many different systems have interpreters that translate bytecode to machine instructions for their particular CPU's. syntax: the way to write something in a language. semantics: the meaning of a language feature or specific piece of code. errors: o compile-time errors. E.g., syntax errors (can't be interpreted as valid code in the language); type errors (misuse of language features so that it is not valid code). o run-time errors. Code compiled, but attempted something illegal/impossible (e.g., divide by zero, out-of-bounds array index, using null like an actual object value). o semantic errors. The code compiles and runs (doing what it implied), but we have written code that doesn't do quite what we want to occur (such as dividing instead of multiplying, or not-quite-finding the maximum in an array). Edit-Compile-Run cycle: When writing code, we first edit a document; then we compile it (to translate to Java bytecode, in this class), which generates the .class file; last, we run it. No matter what development environment, or language, this three-phase cycle is occurring, even when the steps are blurred by DrJava or Eclipse or some other IDE. HelloWorld: be able to write out the "hello, world" program. Although we haven't learned what quite all the parts of it mean, we are making great progress already. Also, running any program amounts to this basic piece of code. o on the test, you won't always have to write code to make a full program; read carefully if a question just asks for a method, or lines of code that would do something when run. We're usually just looking for the couple lines or so that relate to a specific task. Whitespace: any whitespace allowed between any identifiers, operators, etc. (as long as they can be distinguished, we don't even need whitespace: x+=1*foo(a,b); versus x += 1 * foo ( a , b ) ; ). Only exception: can't have newlines within a string literal (between matching ""'s). Thus whitespace doesn't have the indentation meaning that we saw in Python, even though we strongly encourage indentations again. Comments: /* multi line */ and //to-end-of-line styles. identifiers: names for things in our code. Consist of letters, numbers, underscores, and $'s, but don't start with numbers. (Please don't use $'s: they are for code that writes code). keywords: identifiers that have built-in meaning in the language, such as: for while if case switch public private … primitive types versus reference types: o primitive types: 8 basic types where the values are atomic (no sub-portions) and of a known, small, fixed size. They are: boolean, char, byte, short, int, long, float, double. literals: know how to create literals in all primitive types. Recall hexadecimal input, F suffix for float, L suffix for longs. o reference types: types created through a class definition or array definition (whether we write the class or we get it from a library of code, such as java.util or java.lang). casting: a conversion from a value of one type to a value of another type. o implicit casting conversions: when no information is lost, Java will convert between types for us. E.g., from int to double; from short to int; from anything to String (for printing purposes, usually; uses the toString() method for objects). o explicit casting conversions: programmer-specified conversions. Usually required when the conversion loses precision or other information; tells Java that it is 'okay' to perform the lossy action. E.g.: from double to int; from long to short. o Be able to identify when Java performs implicit casts. o Be able to use explicit casts to get data into the right format (type). Creating Variables o declaration: a type and an identifier. Tells Java that there should be a named storage location that can contain one value of the given type, and will be accessed using the given identifier. Only declared variables can be used, ever. Expressions vs. Statements o Expression: a representation of a calculation that can be evaluated to result in a single value; no indication what to do with the value. Be comfortable identifying expressions. Understand the ternary ?: expression. o Statement: a command/instruction for the computer to perform some action; often, statements contain expressions. Be comfortable identifying statements versus expressions. Strings o concatenation: + operator. o implicit conversion of everything to String values when added to a String, or when a String value is needed. o escape sequences: \t, \n, \", \\, etc. o checking for string equality: can't just use ==. Use the equals method: e.g., s1.equals(s2). o Strings are immutable (can't change). printing: via System.out.println(), System.out.print(), System.out.printf(). Scanner: class providing convenient methods to read text input from a source (such as keyboard/System.in). o Be able to use basic scanner methods: nextInt(), nextDouble(), next(), nextLine(), etc. Constant: a 'variable' whose value will never change from its initial value. Indicated with the final keyword. o naming convention: all caps. ex: MIN_HEIGHT, NUM_PONIES. increment/decrement: e.g., x++, ++x, x--, --x. "syntactic sugar" for an increment on the previous or following line. See our slide examples for their semantics. Be ready to examine code using them and report what happens. We ought not have more than one of these per variable per statement… Control Flow heavy use of boolean expressions. (expressions that result in a boolean value). if/if-else. (No elif: since we use {}'s instead of indentation, we can get the same effect with chained if-else's). switch: old-fashioned, fast way to branch. o can only switch based on primitive value (or enum, or String as of Java 1.7). o cases must be values, not expressions. o use break statements to manually leave after each case statement (or don't, with unusual control flow behavior compared to if-elses). o default case can catch all non-cased values. while loop: keep executing body as long as guard (boolean expression) is true. Body might execute zero times (if guard is false first time). do-while loop: like while loop, but guaranteed to run at least once (guard checked after each loop iteration, not before). for loop: init, guard, update. See slides for detailed examples/while loop version. for-each loop: requires an 'Iterator' (arrays are Iterators). Looks like value-based for loop from Python; avoids index usage but still lets us access/modify each element in the Iterator (array, for us for now). break, continue: ways to modify loop/switch control flow. Try not to use them too often, but sometimes they really do make a block of code simpler. Arrays arrays are fixed-length sequences of values, all of a single type. e.g., an array of integers (where each slot holds one integer, like an integer variable). representing an array type: place []'s after a type to indicate an array of that type. String → String[]. int → int[]. Defines an array type. o can add multiple dimensions: int[][], float[][][], etc. Declaration: as always, give a type and an identifier; now the type is an array type. ex: int[ ] xs ; Instantiation: must indicate exact length. o {vals,like,this} //allowed at declaration time only. o new int[]{vals,like,this} // allowed anywhere o new int[10]. (Fills with default values: 0, false, null, as appropriate for the type). accessing/update: using xs[index]. index must be an expression yielding an integer value. o No slicing like Python allowed. usage with loops. A lot of code examples used loops and arrays; be comfortable doing these sorts of things. Classes and Objects Class: a class is a type. It is like a blueprint for making objects. It defines the state that each object will have, and what behaviors (methods) are available for those objects. Object: an object is a value. (A value of a particular class type). It is an instance of its class (one distinct value of that type). It has its own copy of each instance variable and method. Terminology: a type defined through a class is called a "reference type", because we don't have the direct value as with ints; instead, we deal with references to the object value that resides in memory. Variable versus Reference versus Object: A variable is a named container (on the stack). A reference is just a (type,address) pair of an address of an object in memory that also knows what type it points to. Some variables only contain primitive values (no reference), while other variables only contain references (the value is elsewhere). An object is an instance of a class (it's a value), and it resides in the heap memory. The object contains its own copy of each instance variable and method. many references can have the address of the same object; they are called aliases. Since there's only one object involved, updates via one reference are visible through the other references. instance variable: a (non-static) variable declared inside a class, indicating that each object of the class will have its own maintained copy of this variable. E.g., the Square class has a side instance variable. A Coordinate class could have both x and y instance variables. constructor: special method that is used when creating a new object. o no return type listed (returns reference to object of the class's type) o method name must be the class name exactly. o parameters: entirely at programmer's discretion. (Often one per instance variable). o default constructor: If a class definition does not explicitly list a constructor definition, then a default implementation is available: no parameters, and all instance variables receive default values: 0, false, and null (for reference types). Methods named block of code that can be called. defined in a class → thus has access to things defined in the class (no matter what visibility). available modifiers: visibility (public/private/…), static or not, final or not, others we haven't seen. method signature: modifiers, return type, name, parameter list. o example: public static void main (String[] args) parameters: formal parameters defined in parameter list (declares them); when a method is called, the actual parameters (arguments) are supplied to instantiate the formal parameters for this particular invocation of the method. Parameters are local variables. return type: Java enforces that the method will always return a value of the specified return type. o void: indicates that control flow should return without a return-value. Java enforces this, too. All possible paths must guarantee a return of the correct type of value. method overloading: when two methods share the same name, but are still distinguished by their parameter lists, Java allows them to coexist (never ambiguity which one is being called). o only the name, number of params, and types of params can distinguish them. o constructor methods can also be overloaded! This is a great thing. Control Flow: understand how control flow passes through multiple methods as they call each other. Our diagrams of the stack of method frames exhibited both this control flow as well as the location of local data (in the frames, dying as methods were exited) and objects (in the heap – meaning space to the right in our diagrams, which could last arbitrarily long, as long as our references meant Java wouldn't garbage collect them). References the result of a constructor call is not the object itself – it is a reference to that object. A reference is simply an address of an object. Method Calling Conventions (how are actual parameters actually transmitted?) only values are ever sent across from actual parameters of a method call to formal parameters during execution of method body. primitive types: a copy of the primitive value is sent. No effect on the original primitive value is possible (or wherever it may have been stored). reference types: a copy of the reference value is sent (creating an alias). No effect on the original reference is possible; however, these aliases both point to the same object in memory and thus can witness each others' updates to that object. We had examples of each of these, to understand what effect on memory was possible when passing primitive/reference types for parameters. Static modifier that indicates there should only be one definition for the entire class. Note: static doesn't mean "unchanging"! That's what the final keyword is for. static variable: a "class variable". One copy overall, regardless how many objects are made (zero to many, it doesn't matter). Access as Classname.varname, or, as varname inside the class. static method: like a regular method, but cannot use instance variables. Therefore, accessible without an object, directly through class (since no object is used to call it). Access as Classname.method(..), or inside the class definition as just method(..) Usage example: main is static (because we don't make an object of the class to run main). If we want 'helper' methods for main, they must also be static: o static things can't use non-static things! (Local variables in a static method seem like an exception, but it's still inside a static location). Garbage Collection When an object is no longer reachable by your program (no existing chain of references can reach it), Java identifies it as 'garbage', and in the next 'garbage collection' sweep, Java will delete this object (reclaim its memory for later use). garbage collection is automatic in Java – very convenient! (But there are programming tasks where garbage collection may not be desirable/allowed/available). Object class ancestor of all classes. Provides the toString() and equals(Object o) methods, among others. o we can redefine toString() to aid in printing (Java uses this toString method to String-ify any object, quite often with printing in mind). Packages means of grouping Java classes for distribution/usage in multiple projects. utilizes actual folder structure to make package structure. Files must include package statements. aids code reuse, avoids name clashes, organizes code. some class libraries (packages) are provided with Java: java.util, java.lang, etc. a jar file is a "Java Archive": a single-file approach to providing entire libraries of Java classes (still maintains package hierarchy). It is actually just a zip file! Classpath o specifies where Java (javac, java) should look for class definitions. By putting a package's directory on the classpath (or a jar file directly on the classpath), Java can find all classes defined in the package. package usage: o we could just fully qualify a class from a package at each and every usage: java.util.Scanner sc = new java.util.Scanner(System.in); o But we tend to import it first: import java.util.*; // or java.util.Scanner … Scanner sc = new Scanner (System.in); o Consider our package example Wrapper Classes class-versions of the primitive types. o Sometimes only objects are allowed; these also can group more info, like methods and static things, with the type. Auto-boxing: casting between the primitive types and their wrapper-class equivalents occurs implicitly (automatically). Java is able to meaningfully convert between them so it occurs. Scope scope of data is the area in a program where that data can be referenced (used). data declared at the class level can be referenced by all methods in that class. data declared within a method is called "local data", and can only be used in that method. Terminology variables defined in a class, whether static or non-static, are called fields. fields and methods are all called "members" of a class. Visibility class members (and classes) can be given a visibility. For now, just consider public and private. public: anyone with access to this object is allowed to use this public portion of it (whether it's reading/writing a public variable, or calling a public method). private: access to this member is restricted to other members inside the class: meaning that an object can use this private thing while performing its own calculations, but the outside world can't use it. o Good for enforcing encapsulation: presentation to outside world is the public stuff, internal-only representations and methods are private stuff. Based on current view of an object: internal vs. external. (internal: everything available; external: only public stuff available). public methods: "service methods". private methods: "support methods". accessor/mutator methods (getters and setters): ways to individually restore read/write privileges to users of private variables. public stuff defines the "interface" (we called it the API/application programming interface in Python) to the object. Inheritance Allows a new sort of code reuse: similar state (fields) and behavior (methods) can be "inherited" from one class to another. o Establishes a "parent-child" relationship. Also called "superclass/subclass", "base class/derived class". o indicated with extends keyword: class Car extends Vehicle Perhaps most importantly, we now have a supertype/subtype relationship. All the child classes' objects can be used where the parent class's objects were expected. Inheriting things: any fields or methods of the parent class are automatically a part of the child class. They can never be removed. Methods may be re-implemented (with the parent class's approval – non-final methods). Visibility: o public: anyone that can name it can access it. o protected: anyone in the package, and child classes outside the package, can access it. o default (package-private vis.): all in package can see it; nobody outside of the package, not even children, can see it. o private: only visible to this specific class (not to children or co-package members). super: refers to the parent class. o note: this referred to an instance; super refers to a class. o uses: calling parent constructors: super(any,args) finding shadowed (overridden) parent members: super.fieldName constructors: only thing that isn't directly inherited (we must make our own constructors too). o a child class constructor must call its parent constructor as its very first statement, using super(any,args); and correctly matching the parameters list of an actual constructor for the parent class. Java actually adds super(); to any child class constructor that doesn't explicitly call its parent constructor. If no such zero-parameters constructor existed in the parent class, it is a compilation error. single inheritance: Java allows exactly one parent class, always. o if no parent class is specified, the Object class is the parent class. o we can simulate multiple inheritance with interfaces later on. Overriding Methods: o child class can provide a new implementation of a method inherited from parent class. o the method signature must exactly match: name, parameters' types / ordering / number, and also the return type. o No matter at what type we're viewing the child object, if we call the overridden method, we get the child's specialized implementation. we call methods on objects; whenever that particular object was instantiated it had a specific type (the class containing that specific constructor used) → That type always dictates what versions are used, no matter where else (and at what type) we eventually call methods on that object. e.g., we'd get the same implementation of makeNoise(): Labrador spot = new Labrador(..); spot.makeNoise(); // uses Labrador version. ((Dog)d).makeNoise(); // still uses Labrador version. Overriding Fields (a bad, bad idea): you can also override fields, but my opinion is that this will almost always be a programming bug – competing versions of the same-named variable (perhaps different types), where inherited methods use the parent's version, and new/overridden methods use the child's version. Ugly bugly! Difference: Overloading vs. Overriding o overloading: providing same-named methods that purposefully have different method signatures (parameter list #/types), to provide multiple implementations based on different inputs. Especially useful for constructors. Possible without any inheritance involved. The different versions co-exist in peace. o overriding: requires parent/child, inheritance. Child class inherits method, yet re-defines what it will do when that method is called by purposefully having the same method signature, but providing a new body. There can be only one! Object class o it is always an ancestor (parent, grandparent, ..) of every class. o provides a few useful methods: equals(..), toString(), others. o we prefer always overriding these methods. Abstract class: o a class that cannot (yet) be instantiated (we can't make objects of this exact type). o The opposite of an "abstract" class is a "concrete" class. concrete classes may be instantiated o abstract class: achieved by adding the abstract keyword to class declaration. public abstract class Shape { .. } o abstract classes also may optionally include abstract methods: methods that are declared (with abstract modifier), but have no body (a ; instead of {..}). just like all other members, abstract methods will be inherited. o abstract classes may still have child classes. If the child class overrides every abstract method that was inherited, then the child may be concrete. o Just like other classes, an abstract class is a type. The collection of fields and methods we introduced are all guaranteed to exist (and be concrete) for all actual instances from child classes. This is the whole point of introducing an abstract class into our class hierarchy: to have a formal way to group related child classes and use them uniformly. final classes, final methods: o if a class is declared to be final, it may not be extended (no child classes are allowed). o if a method is declared to be final, it may not be overridden (no child class may ever change its implementation of this method). Interfaces Java's "controlled simulation of multiple inheritance". An interface is a type. defines a group of abstract methods that any class may implement. o an interface never has any fields. Add getters/setters to pretend. A class "signs the contract" of an interface by claiming it implements it: public class Car implements Sellable { .. A class "fulfills the contract" by actually implementing (overriding) every single method of the interface. If even a single method from the interface is left out, the class must be abstract (allowing for abstract methods to be passed on to child classes), or else it didn't actually implement the interface, and a compiler error occurs. Examples of interfaces in Java's standard libraries: o Comparable: provides just the compareTo(..) method. Allows an understanding of ordering. Useful for sorting and such. o Iterator: provides hasNext(), next(),and remove(). o Serializable: no methods. But clues Java in to make the class representable for storing in a file or transmitting over a network. Advanced interfaces: o interfaces may inherit from each other! We didn't try this, but it's interesting how rich and related the types we can introduce in Java may be. Enumerations basically, a finite set of values that are grouped into a new type. simple examples: o enum TrafficLight {RED, AMBER, GREEN} o enum Day {MON, TUES, WED, THURS, FRI, SAT, SUN} internal implementation (good mental model): as a class, except that constructors must be private (so no extra values are created anywhere else), and the finite list of values are included at the beginning of the class definition once and for all (as static fields). Otherwise, we can still add methods, fields, all the usual class stuff. Simple Usage: o in general, access with EnumName.EnumValue (e.g., Grade.A). o in switch: access with EnumValue. (Java already knows EnumName b/c of the switch expression) o in foreach loop (utilizing the array returned by values()): for (Grade g : Grade.values() ) { ... } Advanced features: o add three things at once: fields (any visibility) private/package-default constructors (not public: can't be accessed outside package ever, and no protected: enums can't be extended) "constructor calls" to the enumerated values to give state to the values (see slides) o add methods to the entire enumeration. (static or non-static; different visibilities ok except protected) Command-Line Arguments Since running a Java program means running the main method, we can pass in an array of String arguments on the command-line when we execute our Java program: demo$ java MyProgram args here 123 "spacey ones in quotes" too Only strings available: main method signature has (String[] args) parameter list. values are separated by spaces. matching single- or double-quotes may be used to create a single String that contains a space (e.g., "spacey arg"). getting numbers: use Integer.parseInt(s) or Double.parseDouble(s), based on any String s. (e.g., Integer.parseInt(args[0]) ).
欢迎咨询51作业君