Java for the Impatient Lecture 2 Objects References
Java for the Impatient Lecture 2: Objects, References, Constructors, Scope, Wrappers, & Debugging Suggestions.
Announcements Web page: http: //www. cc. gatech. edu /projects/gsams-java Please respond to the surveys; it helps all of us.
Posted Questions Declaration and use of counting variables outside of loop structure? Yes; safe for interpreted language such as Java (with gc & no registers). Allows for common sense. Further: encourages consideration of variable creation and scoping.
Posted Questions What else was wrong with if/else structure from previous slides? As noted last week, use of constants for grade codes (e. g. , A == 90+) would enable efficient maintenance of program.
Posted Questions (cont’d) Use of NTEmacs editor? Not covered herein. Links: http: //www. xemacs. org http: //www. cc. gatech. edu /classes/cs 1502 /ntemacs/ides. html Ask about our lab materials
Posted Questions (cont’d) Improve size of font! How’s this? Also, you might refer to printed slides. Feedback mechanism?
Lecture Topics • References and Pointers in Java – Declaring objects – References vs. pointers – Differences between primitives and objects – Invoking methods belonging to objects • Instantiating and Initializing Objects • Class and Instance Variables
Last lecture, we looked at a model for a box: class Box { int i. Length; int i. Width; int i. Height; public void set. Length (int i. New. Length) { util. ASSERT (i. New. Length > 0, “i. New. Length <= 0”); i. Length = i. New. Length; } // of set. Length public int get. Length ( ) { return (i. Length); } // of get. Length Introduction to Programming, Lecture 3
public void set. Width (int i. New. Width) { util. ASSERT (i. New. Width > 0, “i. New. Width <= 0”); i. Width = i. New. Width; } // of set. Width public int get. Width ( ) { return (i. Width); } // of get. Width public void set. Height (int i. New. Height) { util. ASSERT (i. New. Height > 0, “i. New. Height <= 0”); i. Height = i. New. Height; } // of set. Height
public int get. Height ( ) { return (i. Height); } // of get. Height public int get. Volume ( ) { return ( get. Length( ) * get. Width( ) * get. Height( ) ); } // of get. Volume } // of class Box
Declaring Objects We found that to use this class, we had to ‘declare an object’. “Declaring an object” really means declaring a reference to an object. ” A reference is an implict (or automatic) pointer that can point to an object of the specified class. Introduction to Programming, Lecture 3
Declaring Objects Thus, the code: Box shoe. Box; shoe. Box • does not create an object of class Box. • does create a reference (or ptr) shoe. Box that can point to an object of class Box. • gives us what amounts to a ptr to a Box which is null:
Objects & References shoe. Box; • To make the reference shoe. Box be not null, it is necessary to instantiate it, e. g. , shoe. Box = new Box( ); shoe. Box Instance
Objects & References When Java encounters the keyword “new”, it allocates space in memory for an instance of that object. Now, shoe. Box refers to an instance of class Box, i. e. , an object. Note that the instance (or object) “gets” everything defined in class Box. It has unique copies of all the variables. (Method are shared at byte code level. )
Objects & References A closer look: shoe. Box (a reference to an object of class Box) David Dagon: (Cautionary Note: Here, we suggest that each object gets a unique copy of each method. Although each object is allocated unique memory space for variables, Java efficiently shares methods in common with all objects. For now, you might find it helpful to picture objects in the manner, even though it’s not technically what happens with the heap’s method space in the Java Virtual Machine. ) The data fields (“attributes”): int i. Length; int i. Width; int i. Height; What can be done to that data (“methods”): public void set. Length (int i. New. Length) public int get. Length ( ) public void set. Width (int i. New. Width) public int get. Width ( ) public void set. Height (int i. New. Height) public int get. Height ( ) public int get. Volume ( )
Objects & References Box shoe. Box = new Box(); Box cd. Box = new Box(); Box present = new Box(); shoe. Box The data fields (“attributes”): int i. Length; int i. Width; int i. Height; cd. Box Each time we instantiate a Box, therefore, we get a unique copy to work with. This is one of the most powerful aspect of Object. Oriented What can be done to that data The data(“methods”): fields (“attributes”): int i. Length; public void set. Length (int i. New. Length) int i. Width; public int get. Length ( ) int i. Height; public void set. Width (int i. New. Width) public int get. Width ( ) What canpublic be done that data (int i. New. Height) voidtoset. Height (“methods”): public int get. Height ( ) The data fields (“attributes”): public void set. Length (int i. New. Length) public int get. Volume () int i. Length; public int get. Length ( ) int i. Width; public void set. Width (int i. New. Width) int i. Height; public int get. Width ( ) What can be donepublic to thatvoid dataset. Height (int i. New. Height) public int get. Height ( ) (“methods”): public get. Volume ( ) public void set. Length (intinti. New. Length) public int get. Length ( ) public void set. Width (int i. New. Width) public int get. Width ( ) Programming! . . . present
What do we conclude from this? 1. all objects are dynamic data. 2. because all objects are dynamic, Java “knows” that, whenever we reference an object, it must “follow the pointer”. For example: Java: shoe. Box. set. Length(35); Pseudocode: shoe. Box^. set. Length(35)
References vs. Pointers Java is advertised as “having no pointers. ” In reality, Java is mostly pointers! Every nonprimitive datum must be an object. All objects are dynamic data, accessible via references. And references are really implicit pointers. Java does not have explicit pointers. Outside of JNI, there exists no way to explicitly manipulate pointers. There is no explicit dereferencing operator.
Objects and References Distinguish between primitives and objects. Assignment with Primitives: Code: Memory: int x; x int y; x y x = 5; x=5 y y = x; x=5 y=5 Introduction to Programming, Lecture 3
Objects and References Assignment with References to Objects: Code: Memory: Box box 1; Box box 2; box 1 box 2 L=8, W=5, H=7 box 1 = new Box(8, 5, 7); box 2 = box 1; box 2 box 1 box 2 L=8, W=5, H=7
Objects and References box 1 = new Box(3, 9, 2); box 1 box 2 box 1 = box 2; // Old reference lost! box 1 L=3, W=9, H=2 box 2 L=8, W=5, H=7 L=3, W=9, H=2 L=8, W=5, H=7
Calling Methods • Given what we’ve learned about objects, it follows that methods must be invoked with respect to an object or class. There a few restrictions: 1. Invocation must be unambiguous re: which object or class the method is to act. 2. If the method call appears inside a class, then that class is presumed to contain the appropriate method
Calling Methods FORMAT: <object reference>. <method name> class Wallstreet. Jitters { The class Fed. Res. Chair must have this method! public void panic. Sell ( ) { Fed. Res. Chair greenspan = new Fed. Res. Chair(); if (greenspan. raises. Interest()) { buy. On. Margin(); These methods } must appear in else Wallstreet. Jitters { class! sell. All. Stock(); } } // of panic. Sell } // of Wallstreet. Jitters If the method is NOT inside the class where method declared, then the object must be specified.
Questions? • References and Pointers in Java • Instantiating and Initializing Objects NEXT UP. . . • Constructors and Initialization of Instance Variables • Method Signatures and Overloading • Creating Object Instances • Class and Instance Variables
Constructors Motivation: We need a means of initializing the attributes of a new object (or “instance”) when it is created. Means: “Constructor methods” that are invoked automatically upon “instantiation” (creation) of new object. Example: public Box (int i. New. Length, int i. New. Width, int i. New. Height) { set. Length (i. New. Length); set. Width (i. New. Width); set. Height (i. New. Height); } // of constructor
Constructors Note: Constructor method has same identification as the class. Can now do: Box subwoofer. Box = new Box (46, 82); Equivalent to (but better than) doing: Box subwoofer. Box = new Box; subwoofer. Box. set. Length(46); subwoofer. Box. set. Width(46); subwoofer. Box. set. Height(82);
Constructors Given: public String ( ) public String (String value) A class may have more than one constructor. If so, then each constructor must have unique formal parameter list. Constructor calls must match one of the available constructors Terminology: Creating multiple methods with same identifier is called “method overloading. ” We can: String str. Input 1 = new String (); String str. Input 2 = new String (“A valid constructor. ”); Result: str. Input 1 will be an empty String (with the value ““) str. Input 2 will be a String containing “A valid constructor. ”
class Person { String str. Name; int i. Age; public Person (String str. New. Name){ set. Name (str. New. Name); } // of constructor public Person (String str. New. Name, int i. New. Age) { set. Name (str. New. Name); set. Age (int i. New. Age); } // of constructor public void set. Name (String str. New. Name){ str. Name = strnew. Name; } // of set. Name public void set. Age (int i. New. Age) { i. Age = i. New. Age: } // of set. Age } // of Person Note that the constructors call the modifiers
Java Constructors Can now create a new Person via: Person guitarist 1 = new Person (“Clapton”); Person guitarist 2 = new Person (“Hendrix”, 27); Determining which constructor to invoke requires unique signature. Signature means “identifier and parameter list” Thus, one cannot do: public Person (String str. New. First. Name) {. . . } // of constructor public Person (String str. New. Last. Name) {. . . } // of constructor due to ambiguity.
Java Constructors Default constructors: If you don’t define a constructor, a default constructor will be automatically invoked. The default constructor expects no parameters. The default constructor initializes instance variables to standard Java default values (0 for nums, false for booleans, null for references). Default constructor equivalent to: public Person ( ) { } // of default constructor You can override this by creating your own default constructor (no params) that does contains code.
Java Constructors CANNOT have return values: Do NOT do this: public int Person ( ) {. . . // whatever code } // of constructor public void Person ( ) {. . . // whatever code } // of constructor A return value (including void) means that the method is NOT a constructor, and it won’t be auto-invoked.
Creating Instances of Classes Involves three things: 1. Creating the reference: Box this. Box ; 2. Instantiating the object: this. Box = new Box( ); OR do first two steps at once, e. g. , Box this. Box = new Box( ) 3. Having constructor(s) set initial values: public Box (int i. New. Length, int i. New. Width, int i. New. Height) { set. Length (i. New. Length); set. Width (i. New. Width); set. Height (i. New. Height); } // of constructor With an appropriate constructor, we can do all three at once: Box this. Box = new Box (10, 5, 25);
Instance vs. Class Declarations A distinction that applies to both variables and methods An instance <variable or method> is one that belongs to each object of a class. A class <variable or method> is one that belongs only to the class itself. The keyword static: • indicates a class variable or class method. • absence of the keyword static indicates an instance variable or instance method.
Instance vs. Class Variables Suppose we wanted to track the total number of objects created. Consider: class Human { String str. Name; int i. Population = 0; public Human (String str. Name) { this. str. Name = str. Name; i. Population++; //WRONG! } // of constructor } // of Human Declares a str. Name String for each instance. Thus, each Human will have its own name. But. . . Also declares an i. Population counter for each instance of Human. Thus, each Human will have its own i. Population variable, each having a value of 1. This makes no sense!
Instance vs. Class Variables class Human { String str. Name; static int i. Population = 0; public Human (String str. Name) { this. str. Name = str. Name; i. Population++; } // of constructor NOTE: Each Human does not get an i. Population counter. This declares a single i. Population counter for the class Human itself. It is a class variable. Thus, each Human will increment this single shared counter by 1. } // of Human one change As we know, this declares a str. Name String for each instance. Thus, each Human will have its own name.
Instance vs. Class Variables: When to Use instance variables whenever each object should have its own variable. E. g. , attributes of the particular object. Use a class variable whenever the class itself should maintain a single copy of datum pertaining to all instances of the class. E. g. , population counts. summary data. assigning serial numbers. shared resources.
Instance vs. Class Variables Constants Revisited: class Constant. Example { final int i. MAXSIZE = 10; } // of Constant. Example class Constant. Example { static final int i. MAXSIZE = 10; } // of Constant. Example Declares a single constant for use by all instances of the class. Declares a different-butidentical constant for each instance of the class. Wasteful with zero benefit.
Questions? • Constructors • Class members vs. instance members NEXT UP. . . • Reference – Reference review – == and equals() – Parameter passing • Strings and debugging – Strings and regular objects – Strings and identity – to. String() and debugging main() • Arrays
Objects and References Assignment with References to Objects: Two logical operations available: 1. The operator = (assignment) • It assigns references to objects, i. e. , it manipulates the pointers. • Used in the form: str 1 = str 2 2. The method clone( ) • It copies the object itself. • Used in the form: str 1 = str 2. clone( ); • Not available for all types (requires cloneable interface; interfaces to be discussed later).
Objects and References Assignment operator: = clone(); Two references to a single area of memory Creates a new area in memory so each named reference points to its own object
Objects and References Assignment with References to Objects: Given this: str 1 howdy doody str 2 The statement str 1 = str 2; would give: str 1 str 2 howdy doody Two references to one object But str 1 = str 2. clone(); would give: str 1 doody str 2 doody Two distinct areas of memory
Objects and References Equality with Primitives: int i. Braves; int i. Phillies; i. Braves = 11; i. Phillies = 3; i. Braves 11 i. Phillies 3 System. out. println(i. Braves = = 11); // prints true System. out. println(i. Phillies = = 3); // prints true System. out. println(i. Braves = = i. Phillies); // prints false i. Braves = i. Vikings; 3 i. Phillies 3 System. out. println(i. Braves = = 3); // prints true System. out. println(i. Phillies = = 3); // prints true System. out. println(i. Braves = = i. Phillies); // prints true System. out. println(i. Braves > i. Phillies); // prints false (!)
Objects and References Equality with References to Objects: Two different logical tests available: For primitives 1. The operator = = (equality) • It evaluates whether two references point to the same object. 2. The method equals( ) For objects • It evaluates whether the internal state (i. e. , contents) of one object is identical to the internal state of another object. • It is a special method built-in to the class Object, and is available to all classes you create. In practice you will want to code a version of equals() in your classes, so that you can compare objects.
Objects and References Equality with References to Objects: Box box 1 = new Box(8, 5, 7); Box box 2 = new Box(8, 5, 7); System. out. println(box 1 == box 2); // prints false // does box 1 reference the same // object referenced by box 2? System. out. println (box 1. equals(box 2)); // prints true // does box 1 reference an object // having the same contents as // the object referenced by box 2?
Objects and References Box box 1 = new Box(8, 5, 7); Box box 2 = new Box(8, 5, 7); box 1 L=8, W=5, H=7 box 2 L=8, W=5, H=7 ‘==‘ compares if these references point to the same place in memory! . equals( ) compares if the objects have the same content!
Objects and References The equals( ) method is therefore useful in comparing objects. Here’s an example of a typical equals( ) method: class Box{ // same accessor/modifier methods seen in previous slides public boolean equals (Object o. Temp) { boolean b. Same = false; if (o. Temp instanceof Box) { Box b. Temp = (Box) o. Temp; if ( get. Length() == b. Temp. get. Length() && get. Width() == b. Temp. get. Width() && get. Height() == b. Temp. get. Height() ) b. Same = true; } return b. Same; }// equals “Casting” (covered later) Note: we must decide what constitutes equivalency
Objects and References Explanation of the typical equals( ) method: 1. The keyword ‘instanceof’ merely determines whether or not a reference is of a type of class. String str. Example = “Hello”; if (str. Example instanceof String) System. out. print (“It’s a String!”); We will cover this keyword in more detail later. 2. The steps taken to verify the identity of two objects is inherently based on their context. In the example, two boxes were deemed identical if they had the same dimensions. Other tests could have been used.
Objects and References As Regards the Identity of Objects. There are essentially four tests we can use to compare the identity of objects. Reflexive: for any reference value x, x. equals(x) should return true. Symmetric: for any reference values x and y, x. equals(y) should return true if and only if y. equals(x) returns true. Transitive: for any reference values x, y, and z, if x. equals(y) returns true and y. equals(z) returns true, then x. equals(z) should return true. Consistency: for any reference values x and y, multiple invocations of x. equals(y) consistently return true or consistently return false. (I. e. , it wasn’t just a fluke. ) Why is this important? If you forget to create your own equals() method in a data class, you can still compare the objects with equals(), but the method ‘defaults’ to the most stringent equivalency test possible. That is, equals() will return true only if the two references point to the exact same location in memory.
Java Parameters Pseudocode has 3 basic kinds of parameters: in out in/out You choose between them as appropriate. Java provides two kinds of parameters: pass-by-value (or pb. V): for passing primitives. pass-by-constant-reference (or pb. CR): for passing objects. • The compiler chooses for you based on what is being passed. • In Java, you have no choice.
Java Parameters For all practical purposes, Java provides only the functionality of an in parameter. pass-by-value: • what an in parameter “really is”, i. e. , a value is passed in to the called method. • the called method gets its own copy of the original. pass-by-constant-reference: • when the call is made, the current value of the object is referenced. • the called module can access that value but cannot change it. . . only its temp copy of it can be changed. . . Subtle technical difference. Zero practical difference.
Java Parameters Given the method: public void swap (int i. One, int i. Two) { System. out. println (i. One, + “, “, + i. Two); // line a int i. Temp = i. One; i. One = i. Two; i. Two = i. Temp; System. out. println (i. One, + “, “, + i. Two); // line b } // of swap Then, executing the code fragment: int i. This = 5; int i. That = 6; System. out. println(i. This, + “, “, + i. That); // line c swap (i. This, i. That); System. out. println(i. This, + “, “, + i. That); // line d Gives the output: 5, 6 6, 5 5, 6 ( from fragment line c ) ( from swap line a ) ( from swap line b ) ( from fragment line d )
Java Parameters Given the method: public void test (String str. Input) { System. out. println (str. Input); // line a str. Input = “new string”; System. out. println (str. Input); // line b } // of test Then, executing the code fragment: String str. Temp = “original string”; System. out. println(str. Temp); // line c test(str. Temp); System. out. println(str. Temp); // line d Gives the output: original string new string original string ( from fragment line c ) ( from test line a ) ( from test line b ) ( from fragment line d )
Java Parameters If only have in parameters. . . what to do? !? Think OO! • Data and methods are encapsulated, i. e. , we want all access to, and modification of, data to belong only to the object itself via the object’s methods (provided by its class). • Within a class, data is accessible to methods without going through parameters. • Access from outside should be only by asking the object to “do it for you” via its methods: • accessor ( “get” ) methods: i. e. , functions that return a value • modifier ( “set” ) methods: i. e. , procedures that change data state. • From outside the object, gain access via methods. • Functionality of an out param via modifier methods. • Functionality of an in/out param via an accessor methods (for the in) and a modifier (for the out).
Java Parameters Java parameter variables are (as you’d expect) declared as part of the method to which they are used to provide data. Thus, they are considered local variables with respect to their method. This means that they are automatically created when the method is called (and its frame is pushed onto the stack), and. . . They are automatically deallocated when their method terminates and its frame is popped off the stack. Unlike standard local variables, they do not have to be instantiated or initialized, as those aspects are handled when the actual parameters are passed to the method.
Scope Local variables (declared as a part of method): • Can be seen only from within their method. • Outside of their method, their identifiers have no meaning. Instance and Class variables (declared as part of a class, but not within a particular method): • Can be seen from anywhere in the instance. • This means they can be seen from within methods defined within the class without passing them to the method as parameters. • May or may not be visible beyond (soon). Within a method, local variable identifiers take precedence over instance variable IDers
Preventing Identifier Ambiguity Given: class Person { String str. Name; We want to refer to the instance variable str. Name inside the method, but this code fails! . . . public void set. Name (String str. Name) { str. Name = str. Name; WRONG! } // of set. Name Inside the method, the String str. Name refers to the String in the method signature. This creates a problem: which str. Name is which?
Preventing Identifier Ambiguity Solutions: • Rename the formal parameter: public void set. Name (String str. New. String. Name) { str. Name = str. New. String. Name; } // of set. Name • Use the keyword this to refer to “current object” public void set. Name (String str. Name) { this. str. Name = str. Name; } // of set. Name
Summary so far • Reference – When comparing primitives (int, float, etc. ), use ‘==‘ – When comparing objects (String, or any class you create), use the equals() method – When you create a class that serves as a data type or record, remember to include an equals() method All parameters are in parameters. To change state of object, call modifier methods from within body of method When ids are ambiguous, the most local one takes priority
Strings vis-a-vis Objects Every String is an instance of Java’s built-in class String. Thus, Strings are objects. Java provides extra support for Strings as a convenience because of the frequency with which Strings are used. Three obvious String support features: 1. You need not explicitly instantiate Strings with the ‘new’ keyword. Java automatically instantiates a String object when it encounters a text string within double-quotes. For example. . .
Strings vis-a-vis Objects Assignment w/References to Strings/Objects: Code: Memory: String str 1; Box box 1; str 1 = “Hello World”; box 1 = i. Ln, i. Wd, i. Ht; str 1 box 1 Hello World ERROR: must use new “new” and call constructor
Strings vis-a-vis Objects str 1 box 1 str 1 = “Hello World”; box 1 = new Box(i. Ln, i. Wd, i. Ht); str 2 = new String(); str 2 = “Glib Folksies”; str 2 ? default? Glib Folksies Strings are immutable Hello World i. Ln, i. Wd, i. Ht “default”
Strings vis-a-vis Objects Again, Java automatically creates a new String object whenever it encounters text within double-quote marks. Thus, the code: String str 1 = “Hello World”; accomplishes three things: 1. It creates str 1 as a reference to a String. 2. It creates an instance of a String. 3. It initializes that String to “Hello World”. This is inconsistent with how Java treats standard objects. With standard objects, you must explicitly: instantiate (via new), and initialize (via a constructor).
String Stuff 1. You need not explicitly instantiate Strings. 2. The ‘+’ operater overloaded for Strings, to support concatenation, e. g. , System. out. println(“This string is an example of” + “ one that is too long to fit on one line. Your TAs take off points” + “ for lines that exceed 80 column characters. ”); 3. Several predefined methods provided in built-in class String. Among them are: length( ) // a string knows its length char. At(i. Index) // returns letter at position i. Index; 1 st char is position 0 substring(i. Start. Index) // returns the // substring from position // i. Start. Index to end of string substring(i. Start. Index, i. End. Index) // returns // substring from position i. Start. Index // until but NOT INCLUDING position i. End. Index
Strings Stuff -- Examples String str. Example = “Hello”; 0 H 1 e char c = str. Example. char. At(1); 2 l // c gets ‘e’ String str. British. Howdy = str. Example. substring(1); str. British. Howdy ---> “ello” String str. Lecture. Room. Temperature = str. Example. substring(0, 4); str. Lecture. Room. Temperature --> “Hell” 3 l 4 o
Strings vis-a-vis Objects Also. . . One cannot change contents of a String object. (We say: “Strings are immutable”. ) You may think you are modifying a String. But, what happens in memory is: * a new String is created * your old String may be ‘garbage collected’; you no longer have a reference to the old String For example: String str 1 = “Hello World” str 1 = str 1. substring(4) str 1 Hello World
Objects and References: The special case of String Caution: In the next few slides, we will cover what is one of the more confusing part of Java for new students. If you get lost, just remember what we’ve covered so far: 1. When comparing primitives (int, float, etc. ), use ‘==‘ 2. When comparing objects (String, or any class you create), use the equals() method. 3. When you create a class that serves as a data type or record, remember to include an equals() method. In the slides ahead we will note some rare exceptions where the ‘==‘ comparison will work for objects.
Objects and References: Review of the normal case Remember the general pattern of our previous example: box 1 = new Box(1, 2, 3); box 2 = new Box(8, 5, 7); box 1 = box 2; box 1 System. out. println(box 1 = = box 2); // prints true // Does box 1 reference the same // object that box 2 references? box 2 System. out. println(box 1. equals(box 2)); // prints true // Does box 1 reference an object that has // the same contents // as the object referenced by box 2? L=1, W=2, H=3 L=8, W=5, H=7
Equality with References to Objects: Strings are special As part of the Java Language Specification (the ‘rules’ for the Java Language), Strings have a special characteristic. It turns out that in some circumstance (BUT NOT ALL), you can use ‘==‘ to compare Strings, in addition to. equals(). Consider: String str. Hello 1 = “Hello”; String str. Hello 2 = “Hello”; We would expect these lines to produce the following memory changes str. Hello 1 str. Hello 2 Hello In fact, it produces the following results in memory: str. Hello 1 str. Hello 2 Hello
Why are Strings treated differently? Strings are sometimes a special case of equivalency in Java. When the compiler encounters the lines: String str. Hello 1 = “Hello”; String str. Hello 2 = “Hello”; the compiler is smart enough to know that the two Strings are identical. So, it decides it will save a few bytes of memory and point to the same location in memory. The same result would occur even if you wrote: String str. Hello 2 = “Hell” + “o”; This means that for the above lines of code, equals() and ‘==‘ both work: System. out. println (str. Hello 1. equals(str. Hello 2)); // true System. out. println (str. Hello 1 == str. Hello 2); // also true,
Exception to the exception with String But this special case for ‘==‘ comparison of Strings DOES NOT ALWAYS WORK. . . Consider: If one of the Strings were created with use of the ‘new’ keyword, the two Strings would no longer share memory. (That is, ‘==‘ would be false, but equals() would still be true, if the contents of the Strings are the same. ) So, there’s an exception to the exception for Strings when you don’t use the String exception to object instantiation. Confusing? Exceptionally so! LESSON: DON’T USE THE EXCEPTION. Don’t compare Strings, or any Object, with ‘==‘, even if you think the exception will apply.
Debugging Strategies Incremental Programming: The Idea: Find and repair bugs “in the small” before you have a program with several components. The hardest thing is finding the errors. So, find them as you create each class. Thus, do not: • write your entire program, then • type in your entire program, then • attempt to test your entire program Instead: • design your program at high level, focus on one class at a time, • for each class, write and test before going on to the next one.
Debugging Strategies Potential problems with state objects: State incorrectly modified by modifer methods. State incorrectly represented by accessor methods. Need: A way to see the state of the object. Means: public String to. String ( ) • Create one “to. String” method per class. • Use it to put a reference to object directly in: System. out. println ( );
Example of using to. String: If have method for Class Box: public String to. String ( ) { String str. Return = new String(“Box: length = “ + i. Length + “, Width = “ + i. Width + “height = “ + i. Height); return str. Return; } // of to. String Then we can do: System. out. println ( subwoofer. Box );
Debugging Strategies • According to Java, you only need one main per program. . . not one per class. • But Java doesn’t know how to program! • To test/debug a class, create a main method for the class as part of the class. . . • Include in “test mains” the: declaration of variables the invocation of methods the generation of output (e. g. using to. String()) that will allow you to see what the class actually does! 25
Sumary so far • Strings and debugging – Strings are objects • Concatenation with + operator • Lots of useful string manipulation methods in java. lang. String – Strings are special: • Don’t need to instantiate; can initialize by assignment • Can usually compare with ==, but don’t rely on it – to. String() and debugging main() • Define a to. String() method for debugging each class
Collections • Thus far, data has been simple structures • Java also allows collections of data: - as part of the API - in user defined classes • Important collections include: - arrays (today) - vectors - linked lists - trees (Note: In Java, Strings are not arrays or lists of characters)
Arrays The Idea: • Same concepts you know from Pseudocode • A few differences in implementation Java array declaration: <elements. Type>[ ] <array. IDer> = new <elements. Type>[<size>]; e. g. : to declare an array of ten ints for storing numerical grades. . . int[ ] i. Grade. Array = new int[10]; Array declaration error: using parentheses, not brackets, e. g. , int[ ] i. Grade. Array = new int(10);
Arrays Example: • declare i. Grade. Array of 10 ints • initialize all 10 values to 0 int[ ] i. Grade. Array = new int[10]; int i; // when declaring and manipulating arrays, you may // use the single-letter IDers i, j, k for indices // due to convention (everybody knows what it is) for (i=0; i < i. Grade. Array. length; i++) { i. Grade. Array[i] = 0; } // for loop Great idea! if you change the array size, you need only change the instantiation.
Arrays Notes: • All arrays are objects, thus you must declare a reference, and instantiate it, and initialize it • Arrays know their own length • length is a field, not a method • Arrays are statically sized: you cannot change the length after declaration.
Arrays More Notes: • Array indices begin at 0, not at 1 • So, length is one greater than i. MAX_INDEX • Thus, an error if you do: int[ ] i. Grade. Array = new int[10]; int i; for (i=1; i <= i. Grade. Array. length; i++) { i. Grade. Array[i] = 0; } // for loop • Code above attempts to access elements 1. . 10 • But. . . you have indices 0. . 9 • So: it misses the 1 st element (which is at index 0) it tries to go past 10 th element
Arrays Example: represent a student who • keeps track of quiz and program grades. • can add a quiz grade and a program grade. class Java. Student { public static final int i. MAX_NUM_QUIZ = 8; public static final int i. MAX_NUM_PROG = 9; int[ ] i. Quiz. Array; int i. Quiz. Index = 0; int[ ] i. Prog. Array; int i. Prog. Index = 0; continued
Arrays public Java. Student( ) { // constructor to initialize elements to 0 i. Quiz. Array = new int[i. MAX_NUM_QUIZ]; for (i. Quiz. Index=0; i. Quiz. Index < i. MAX_NUMQUIZ; i. Quiz. Index++) i. Quiz. Array[i. Quiz. Index]=0; i. Quiz. Index = 0; i. Prog. Array = new int[i. MAX_NUM_PROG]; for (i. Prog. Index=0; i. Prog. Index < i. MAX_NUM_PROG; i. Prog. Index++) i. Prog. Array[i. Prog. Index]=0; i. Prog. Index = 0; } // constructor
Arrays public void add. Prog. Grade (int i. New. Prog. Grade) { i. Prog. Array[i. Prog. Index] = i. New. Prog. Grade; i. Prog. Index++; } // of add. Prog. Grade public void add. Quiz. Grade (int i. New. Quiz. Grade) { i. Quiz. Array[i. Quiz. Index] = i. New. Quiz. Grade; i. Quiz. Index++; } // of add. Quiz. Grade } // of CS 1502 Student
Arrays Potential Errors: out of range indices: • Compile time: bad int value known, e. g. , i. Quiz. Array[9] = i. New. Quiz. Grade. • Runtime: bad int value via variable, e. g. , i. Quiz. Array[i. Quiz. Index] = i. New. Quiz. Grade; Design issues: This example is legal Java, but is it good OO?
Arrays Example: represent a franchised cafeteria that has limits on: trays, flatware, seats. class Cafeteria { int i. Sum. Trays = 0; int i. Sum. Flatware = 0; int i. Sum. Seats = 0; public Cafeteria(int i. Sum. Trays, int i. Sum. Flatware, int i. Sum. Seats) { set. Sum. Trays( i. Sum. Trays ); set. Sum. Flatware( i. Sum. Flatware ); set. Sum. Seats( i. Sum. Seats ); } // of constructor /* We assume accessors, modifiers: get. Trays( ), set. Trays( ), etc. -- are implemented here*/ } // of Cafeteria
public class Primes { public static void main (String arg[ ]) { int MAX = 100; boolean[ ] b. Prime = new boolean[MAX]; b. Prime[1] = false; /* set all candidates to true */ for (int i=2; i< MAX; i++) b. Prime[i] = true; Note: Here, the important information is stored as the index value of the array; we don’t place numbers in the array itself. /* set to false all multiples of the counters */ for (int I = 2; I < MAX/2; i++) for (int j = 2; j < MAX/i; j++) b. Prime[i* j]=false; /* print results */ for (int i=1; i<MAX-1; i++) if (b. Prime[i]) System. out. println (i + " is prime"); } // main } // class Primes
Arrays An array may be declared to be: an array of primitives, or an array of objects. Arrays are objects, even if the array contains primitives. (Array identifier references an object). If an array of objects, then: the array IDer is a reference to the array each array element is a reference to an object of the class specified as elements Instantiating the array object does not instantiate the various element objects to which it refers. Element objects must be explicitly instantiated and initialized.
Arrays Then, the code segment: Cafeteria cafeteria 1 = new Cafeteria(10, 20, 30); Cafeteria cafeteria 2; produces: i. Sum. Trays = 10 i. Sum. Flatware = 20 i. Sum. Seats = 30 cafeteria 1 cafeteria 2
Arrays and the code segment: Cafeteria[ ] cafeteria. Array = new Cafeteria[5]; produces: cafeteria. Array which could then be initialized: int i; for ( i = 0; i < cafeteria. Array. length; i++) cafteria. Array[i] = new Caferia(10, 20, 30);
Arrays giving: i. Sum. Trays = 10 i. Sum. Flatware = 20 i. Sum. Seats = 30 cafeteria 1 ia r te s e af ect c 6 bj o cafeteria 2 7 o b in ject tot s al cafeteria. Array i. Sum. Trays = 10 i. Sum. Flatware = 20 i. Sum. Seats = 30
Arrays. . . ct je tal ob to ria in te ts fe ec ca bj 1 2 o but the code segment: int i; for ( i = 0; i < cafeteria. Array. length; i++) { cafeteria. Array[i] = cafeteria 1; } // of for loop initialization produces: cafeteria. Array cafeteria 1 i. Sum. Trays = 10 i. Sum. Flatware = 20 i. Sum. Seats = 30
Arrays - Creation • Declaration and instantiation: int[] my. Ints = new int[10]; my. Ints[0] =3; • Static initialization: int[] my. Ints = {1, 2, 5, 6, 7, 4, 3, 23, 4, 4, 3, 3, 5};
Multi-Dimensional Arrays int [][] my. Two. Dim. Array; my. Two. Dim. Array = new int[10][5]; • Quiz yourself: • Valid? String[][] s; s = new String[10][]; • Valid? s = new String[][10];
Static multidimensional initialization: String s[][] = {{"Static", "multidimensional", "initialization", "of"}, {"arrays", "requires", "the", "use"}, {"of", "nested", "parens"} };
Static arrays of multidimensional requires nested initialization the parens of use null Results: • Note ‘null’ default • Note ordering s[2][1] --> “the”
Summary of Arrays • Arrays – All arrays are objects (you have to declare, instantiate, and initialize) – Arrays are either arrays of primitive elements (e. g. int) or arrays of objects (really references to objects) – Arrays are statically sized: you can’t change length after Use Array. length in for loops to avoid “off-by-one” errors – 2 D arrays are arrays of arrays • Don’t go yet, there’s one more slide….
- Slides: 96