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
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 = 999w2.d = 202 w2.s = 999w3.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
A Picture
class Widget { static int s; int d;}
Widget Object static int s; int d;
Widget Object static int s; int d;
Widget Object static int s; int d;
w1
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
Perhaps an example?
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 referenceto 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.
Questions?
Debugging Java Code
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 PointerException
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 Debuggingclass 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; }
// pppomitted tosave space!
// pppomitted tosave 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 getSystem.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; }
// pppomitted tosave space!
// pppomitted tosave 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; }
// pppomitted tosave space!
// pppomitted tosave 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
Example
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;
w1
Example
Assume we have a class Widget
Widget w1;
Widget w2;
w1 = new Widget();
w2 = w1;
w1 = new Widget();
w2 = null;
w1
w2
Example
Assume we have a class Widget
Widget w1;
Widget w2;
w1 = new Widget();
w2 = w1;
w1 = new Widget();
w2 = null;
w1
w2
widget object (1)
Example
Assume we have a class Widget
Widget w1;
Widget w2;
w1 = new Widget();
w2 = w1;
w1 = new Widget();
w2 = null;
w1
w2
widget object (1)
Example
Assume we have a class Widget
Widget w1;
Widget w2;
w1 = new Widget();
w2 = w1;
w1 = new Widget();
w2 = null;
w1
w2
widget object (1)
widget object (2)
Example
Assume we have a class Widget
Widget w1;
Widget w2;
w1 = new Widget();
w2 = w1;
w1 = new Widget();
w2 = null;
w1
w2
widget object (2)