400 likes | 428 Views
Static?. Static. Not dynamic class Widget { static int s; int d; // dynamic // or instance // variable }. Instantiation. Widget w1 = new Widget(); Widget w2 = new Widget(); Widget w3 = new Widget(); There are now 4 variables w1.d
E N D
Static • Not dynamic class Widget { static int s; int d; // dynamic // or instance // variable }
Instantiation Widget w1 = new Widget(); Widget w2 = new Widget(); Widget w3 = new Widget(); There are now 4 variables w1.d w2.d w3.d • Widget.s, w1.s, w2.s, w3.s are all the same!
class Widget { int d; static int s; public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); Widget w3 = new Widget(); w1.d = 101; w2.d = 202; w3.d = 303; Widget.s = 999; System.out.println("w1.d = " + w1.d + " w1.s = " + w1.s); System.out.println("w2.d = " + w2.d + " w2.s = " + w2.s); System.out.println("w3.d = " + w3.d + " w3.s = " + w3.s); } } w1.d = 101 w1.s = 999 w2.d = 202 w2.s = 999 w3.d = 303 w3.s = 999
Why • Think of static variables as living in the class • Dynamic variables live in the object • BUT note that the objects can refer to the static variables with no problem
Note • The dynamic or instance variables were all accessed using their reference. • The static (sometimes called class) variables can be accessed using a reference or the class name
Widget Object static int s; int d; Widget Object static int s; int d; Widget Object static int s; int d; A Picture w1 class Widget { static int s; int d; } w2 w3
So why static methods? • A method that only refers to static variables and which could be invoked using: • class.method() • must be marked static
class Widget { int serial; static int count; public Widget() { count++; serial = count; } public int getSerial() {return serial;} public int getCount() {return count;} public String toString() { return "Widget " + getSerial() + " of " + getCount(); } public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); System.out.println(w1); System.out.println(w2); System.out.println(getCount()); } }
class Widget { int serial; static int count; public Widget() { count++; serial = count; } public int getSerial() {return serial;} public int getCount() {return count;} public String toString() { return "Widget " + getSerial() + " of " + getCount(); } public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); System.out.println(w1); System.out.println(w2); System.out.println(getCount()); } } Can't make static reference to method int getCount() in class Widget.
class Widget { int serial; static int count; public Widget() { count++; serial = count; } public int getSerial() {return serial;} public static int getCount() {return count;} public String toString() { return "Widget " + getSerial() + " of " + getCount(); } public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); System.out.println(w1); System.out.println(w2); System.out.println(getCount()); } }
class Widget { int serial; static int count; public Widget() { count++; serial = count; } public int getSerial() {return serial;} public static int getCount() {return count;} public String toString() { return "Widget " + getSerial() + " of " + getCount(); } public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); System.out.println(w1); System.out.println(w2); System.out.println(getCount()); } } Why not Widget.getCount()
class Widget { int serial; static int count; public Widget() { count++; serial = count; } public static int getSerial() {return serial;} public static int getCount() {return count;} public String toString() { return "Widget " + getSerial() + " of " + getCount(); } public static void main(String args[]) { Widget w1 = new Widget(); Widget w2 = new Widget(); System.out.println(w1); System.out.println(w2); System.out.println(getCount()); } } Can't make a static reference to nonstatic variable serial in class Widget.
Debugging • Beginning programmers typically find just getting a program to compile a big challenge • Error messages are often meaningless • Error messages are often in the “wrong” place • Error messages often suggest a course of action which is dead wrong • Sometimes the excitement of getting the program to compile leads the programmer to forget that the program should also work. • What can go wrong • Wrong answer • Illegal operation (exceptions)
Strategies • Write it right the first time. It isn’t easier to find errors later! • The compiler only finds language errors not logic errors. • Read the error message carefully. Sometimes they contain useful information. • A null pointer exception is not mysterious! Queue q; q = null; q.enqueue(5); Null Pointer Exception
Strategies • Let the computer help you find the errors • In every class define a constant public final static boolean DEBUG = true; • When things aren’t working add lines of code like this: if(DEBUG) { System.out.println (“method> location variable = “ + variable); } • Keep adding these statements until the source of the problem is found • Errors are normally caused by the computer doing what you told it to do! • When the code works...change DEBUG to false • Don’t remove the if(DEBUG) statements
The Main • A typical Java program consists of a bunch of class files. • An obvious question might be, “How does it all start up?” • No matter how many classes are available, one of them must be sent to the JVM to start things off. • The mechanism is simple. Any file sent to the JVM must have a public static method called main. That’s where the action starts
The Main for Debugging • Starting with “main” has an additional benefit. • As each class is written it can have its own main sometimes known as a debugging or test main. • This test main should test all the methods in the class paying special attention to special or limiting cases. • Once testing is complete: Leave the test main in the source file! • It won’t have any effect and may be beneficial if later modifications are made to the class.
The Main for Debugging class Driver { ... public static void main(String args[]) { ... } } class Stack { ... public static void main(String args[]) { ... } } class Menu { ... public static void main(String args[]) { ... } } class Widget { ... public static void main(String args[]) { ... } } class Blivet { ... public static void main(String args[]) { ... } }
Debugging • Write code in small “chunks” • Compile and test frequently (whenever possible) • Use the test main in every class! • Let’s create a linked list class that will hold Student Records. • We’ll start by creating a StudentRecord class.
StudentRecord class StudentRecord { private String name; private double gpa; private int ssn; public StudentRecord(String n, double g, int s) { setName(n); setGpa(g); setSsn(s); } public void setName(String n) { name = n; } public void setGpa(double g) { gpa = gpa; } public void setSsn(int s) { ssn = s; } public String getName() { return name; } public double getGpa() { return gpa; } public int getSsn() { return ssn; } // ppp omitted to save space!
toString or ! toString • You may recall that System.out.println takes as a parameter a String. • So why does it work if we say: System.out.println(5); • Java converts it for us! • Java also has a similar behavior when the argument is a reference to an object • If we type: StudentRecord sr; // Make one here... System.out.println(sr); • We really get System.out.println(sr.toString());
So the wise programmer... • Always define a toString() method in every class. • THE toString() METHOD DOES NOT PRINT ANYTHING • it merely returns a String to its caller • If you omit the toString() method, Java will use a default toString() which probably won’t help you to debug. • What should toString() look like?
StudentRecord toString // Precon: fields should be initialized // Purpose: return string representation // Postcon: no change to StudentRecord public String toString() { String retVal; retVal = getName() + “ “; retVal += getGpa() + “ “; retVal += getSsn(); return retVal; }
Now the test main! // Purpose: test main public static void main(String args[]) { StudentRecord sr; sr = new StudentRecord( "George Burdell", 4.0, 987654321); System.out.println( "Should be George Burdell 4.0 987654321:" + sr); sr.setName("Bill Gates"); sr.setSsn(123456789); sr.setGpa(0.3); System.out.println( "Should be Bill Gates 0.3 123456789:" + sr); } } // Studentrecord
And the test! C:\demo>java StudentRecord Should be George Burdell 4.0 987654321: George Burdell 0.0 987654321 Should be Bill Gates 0.3 123456789: Bill Gates 0.0 123456789 C:\demo>
What's wrong? class StudentRecord { private String name; private double gpa; private int ssn; public StudentRecord(String n, double g, int s) { setName(n); setGpa(g); setSsn(s); } public void setName(String n) { name = n; } public void setGpa(double g) { gpa = gpa; } public void setSsn(int s) { ssn = s; } public String getName() { return name; } public double getGpa() { return gpa; } public int getSsn() { return ssn; } // ppp omitted to save space!
Corrected class StudentRecord { private String name; private double gpa; private int ssn; public StudentRecord(String n, double g, int s) { setName(n); setGpa(g); setSsn(s); } public void setName(String n) { name = n; } public void setGpa(double g) { gpa = g; } public void setSsn(int s) { ssn = s; } public String getName() { return name; } public double getGpa() { return gpa; } public int getSsn() { return ssn; } // ppp omitted to save space!
Under the Hood • A detail that we need to clarify • In Pseudocode, we defined a record • Now we define a class • In Pseudocode, we could make record on the heap • Now we can make an object on the heap • In Pseudocode, the new operator returned a a value we stored in a pointer variable • Now the new command will return a value that we’ll store in a reference
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example w1
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example w1 w2
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example w1 widget object (1) w2
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example w1 widget object (1) w2
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example widget object (2) w1 widget object (1) w2
Assume we have a class Widget Widget w1; Widget w2; w1 = new Widget(); w2 = w1; w1 = new Widget(); w2 = null; Example widget object (2) w1 w2