BM214E Object Oriented Programming Lecture 7
References
References Revisited What happens when we say: int x; double y; char c;???
We create variables x y c Variable: Symbol plus a value
Assume that we have class Box class LLNode as well as the usual suspects: class String, etc.
What happens when we say Box b; LLNode head; String s;
We create variables b head Reference variables hold the location of objects. If they aren't referencing an object what is their value? s Box LLNode String Java keeps track of what type of object each reference can "point" to.
Common Errors! Box b = new Box(1, 2, 3);... Box b = new Box(4, 5, 6);...
Should be: Box b = new Box(1, 2, 3);... b = new Box(4, 5, 6);...
Common Errors! Box b = new Box(1, 2, 3); b = anotherbox;
Should be: Box b; b = anotherbox;
Common Errors! class Whatever { Box b; // Constructor public Whatever() { Box b = new Box(1, 2, 3);
Should be: class Whatever { Box b; // Constructor public Whatever() { b = new Box(1, 2, 3);
Understanding References Key to understanding Arrays of Objects Testing for Equality of Objects Passing Objects to Methods Assignment vs. Clone etc. For example...
Understanding Equality The key to understanding equality comes from knowing how Java handles references and primitives. First, here s the rule: When comparing primitives, use ==, thus: if ( icount == imaximum ) // etc. When comparing objects, use.equals(), thus: if ( box1.equals(box2) ) // etc. Now, let s consider WHY...
Testing Equality: Primitives Equality with Primitives: int x; int y; x = 11; y = 3; x: 11 y: 3 System.out.println(x == 11); System.out.println(y = = 3); System.out.println(x = = y); // prints true // prints true // prints false x = y; x: 3 y: 3 System.out.println(x = = 3); System.out.println(y = = 3); System.out.println(x == y); System.out.println(x > y); // prints true // prints true // prints true // prints false
Testing Equality: Objects 1. Are the references equal? Test with == In other words, are both references pointing to exactly the same object? Considered to be the most stringent test for equality
Testing Equality: Objects 2. Are the objects themselves equal? The answer depends on your definition of equality! Create an equals() method which compares the internal state of the object with another object passed in as a reference. You need to create this method for every class where you will need to compare objects for equality
Example class Rectangle { int len, wid; String name; // Constructor and basic get/set methods not shown public boolean equals(object o) { boolean retval = false; if(o instanceof Rectangle) { Rectangle r = (Rectangle)o; if(r.getlen() == len && r.getwid() == wid) retval = true; } return retval; }
Example public static void main(string args[]) { Rectangle r1 = new Rectangle(3,4,"Bob"); Rectangle r2 = new Rectangle(3,4,"Ted"); Rectangle r3 = new Rectangle(8,7,"Bob"); Rectangle r4 = r1; String s = "Goofy"; System.out.println(r1.equals(r2)); System.out.println(r1.equals(r3)); System.out.println(r1.equals(r4)); System.out.println(r1.equals(s)); } } // Rectangle
Recall the LLNode public boolean equals(object o) { boolean retval = false; if(o instanceof LLNode) { retval=getdata().equals(((llnode)o).getdata()); } return retval; }!!!?? data next data next
The LLNode public static void main(string args[]) { LLNode n4 = new LLNode("delta", null); LLNode n3 = new LLNode("gamma", n4); LLNode n2 = new LLNode("beta", n3); LLNode n1 = new LLNode("alpha", n2); LLNode tester = new Node("beta", null); } System.out.println(n1.equals(tester)); System.out.println(n2.equals(tester)); System.out.println(n3.equals(tester)); System.out.println(n4.equals(tester));
Note! The.equals() method in class Object is simply ==
Scope
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 What we want: class Person { String strname;... public void setname (String strname) { WRONG! strname = strname; } // of setname Inside the method, the String strname refers to the String in the method signature. This creates a problem: which strname is which?
Preventing Identifier Ambiguity What we get: class Person { String strname;... public void setname (String strname) { WRONG! strname = strname; } // of setname Inside the method, the String strname refers to the String in the method signature. This creates a problem: which strname is which?
Preventing Identifier Ambiguity Solutions: Rename the formal parameter: public void setname (String strnewstringname) { strname = strnewstringname; } // of setname Use the keyword this to refer to current object public void setname (String strname) { this.strname = strname; } // of setname Preferred with Javadocs
Shadowing
Shadowing Refers to "hiding" something that still exists Simple case today Will come back to this topic during discussion on inheritance
class Widget { Shadowing public String name; public void somemethod(int i) { String name; /* Shadows instance variable */ name = "Bob"; this.name = "Wally"; /* Accessing the shadowed variable! */
Chaining
Some Constructors class Rectangle { private int length, width; private String name; public Rectangle () { setlength(0); setwidth(0); setname("unnamed"); } // constructor public Rectangle (int l, int w, String n){ setlength(l); setwidth(w); setname(n); } // constructor public Rectangle (int l, int w) { setlength(l); setwidth(w); setname("unnamed"); } // constructor
Constructor "Chaining" class Rectangle { private int length, width; private String name; public Rectangle () { this(0,0,"unnamed"); } // constructor public Rectangle (int l, int w, String n){ setlength(l); setwidth(w); setname(n); } // constructor public Rectangle (int l, int w) { this(l, w,"unnamed"); } // constructor
Add a count? class Rectangle { private int length, width; private String name; private static count = 0; public Rectangle () { setlength(0); setwidth(0); setname("unnamed"); count++; } // constructor public Rectangle (int l, int w, String n){ setlength(l); setwidth(w); setname(n); count++; } // constructor public Rectangle (int l, int w) { setlength(l); setwidth(w); setname("unnamed"); count++; } // constructor
Add a count, simpler with "Chaining" class Rectangle { private int length, width; private String name; private static int count = 0; public Rectangle () { this(0,0,"unnamed"); } // constructor public Rectangle (int l, int w, String n){ setlength(l); setwidth(w); setname(n); count++; } // constructor public Rectangle (int l, int w) { this(l, w,"unnamed"); } // constructor
Arrays
Arrays An array may be declared to be: an array of primitives, or an array of objects (actually references!!!). The Array itself is an Object, even if the array contains primitives. (Array identifier references an object). If an array of objects, then: the array identifier is a reference to the array object 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.
Example: Imagine a Flatware object which keeps track of: knives, forks and spoons. class Flatware { int knives = 0; int forks = 0; int spoons = 0; public Flatware(int knives, int forks, int spoons) { setknives(knives); setforks(forks); setspoons(spoons); } // of constructor /* We assume accessors, modifiers--getknives(), setknives(), etc. -- are implemented here */ } // of Flatware Arrays
Arrays Then, the code segment: Flatware fw1 = new Flatware(10, 20, 30); Flatware fw2; produces: fw1 fw2 knives = 10 forks = 20 spoons = 30
Arrays and the code segment: Flatware[ ] flatwarearray = new Flatware[5]; produces: flatwarearray which could then be initialized via: int i; for ( i = 0; i < flatwarearray.length; i++) { flatwarearray[i] = new Flatware(10, 20, 30); } // of for loop initialization
giving: Arrays fw1 fw2 flatwarearray knives = 10 forks = 20 spoons = 30 knives = 10 forks = 20 spoons = 30 knives = 10 forks = 20 spoons = 30 knives = 10 forks = 20 spoons = 30 knives = 10 forks = 20 spoons = 30 knives = 10 forks = 20 spoons = 30
Arrays but the code segment: int i; for ( i = 0; i < flatwarearray.length; i++) { flatwarearray[i] = fw1; } // of for loop initialization produces: flatwarearray fw1 knives = 10 forks = 20 spoons = 30
Review: Array Creation Declaration int myints[]; int[] myints; Instantiation myints = new int[10]; Declaration and instantiation: int[] myints = new int[10]; Access to individual element myints[3] = 9; x = myints[4]; Static initialization int[] myints = {1,2,5,6,7,4};
Multi-Dimensional Arrays int[][] mytwodimarray; mytwodimarray = new int[10][5]; Quiz Yourself! Valid? String[][] s; s = new String[10][]; Valid? s = new String[][10]; //YES! // NO!
Static multidimensional initialization: String s[][] = {{"Static", "multidimensional", "initialization", "of"}, {"arrays", "requires", "the", "use"}, {"of", "nested", "curlies"} }; Creates: Static multidimensional Initialization of arrays requires the use of nested curlies (null)
Arrays Summary of 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 declaration; arrays know their own length Use Array.length in for loops to avoid off-by-one errors 2D arrays are arrays of arrays
Questions?