- Up to this point, we've made a big deal that all member fields
in a class have separate copies in each instance of the class, so
if we have two variables: Point one,two; then one.x is a
different variable from one.y.
- There is an exception to this, one that is very similar to C++,
if you happen to have seen it. We can declare a member field
as static. In that case the variable is shared
between all instances.
class Point {
int x,y;
static int num;
}
- In this case one.num is the same variable as two.num. If I
change one.num, I change two.num as well. Try it.
- This is handy for information that should be shared across all
objects of the class. Imagine you wanted to establish a unique ID
number to each object. Keeping a static field for the next free
ID would be handy.
- But there's one little problem, what is the value of num
initially? Shouldn't it be 0? But we can't initialize it because
we don't have an object yet in order to name it. The answer is to
use the name of the class not the name of a variable
instance of the class. We could make num 0 by saying Point.num=0;
- Stylistically, since we can always access num via the
class name instead of a variable name, it has become preferred
that we always do. This way it signals to the reader of
our code that this is not a regular member field.
- Another use for the static modifier on fields is in conjunction
with final. Final means that the value of this thing
cannot be changed, which makes it good for a constant:
class Tools {
final double SQRT2 = 1.41421356;
...}
but the problem with this is we couldn't access this thing without
creating an object of type Tools:
Tools t = new Tools();
double d = t.SQRT2;
That seems wasteful, but if static fields exist even when no
objects of that type exist, thaen we can declaer it as:
class Tools {
final static double SQRT2 = 1.41421356;
...}
and access it directly using the class name:
double d = Tools.SQRT2;
- We've seen the keyword static also applied to methods, and we
said this means we're "not doing OOP, but rather
structured/procedural programming." This is sort of right, but
it's more complicated than that.
- A static method still is a member method of that class, but like
static fields, it is not associated with any particular object.
What this means is that inside this method, you cannot access any
member fields that are not static. If we added the following to
Point:
static int foo() {
return x;
}
we would get a compile time error: "non-static variable xcannot be
referenced from a static context."
but we could access static fields:
static int foo() {
return num;
}
- Static methods are used in 2 cases:
- When we only want to access static fields in the class,
like the example above.
- When we don't need to access any of the state of an object
because all the information we need is in the arguments.
This is usually for utility functions that are best called
in a structured/procedural way. The built in math functions
are all examples of that:
Math.pow(3,2);
- Wait, what about main()? Why is that static? well, main isn't really special at all, it's just another method in another class. Look at how we run our program form the command line: java Main.
- What happens is not that your program starts running at main() the way it does in C++, but we start running in the virtual machine, and the vm is instructed to call the static method in the class you passed as an argument on the command line: Main.main(s);
- Does that mean we could have instructed it to start differently? absolutely! We can put a main() method in every class we write. Try adding main to our point class and running that: java Point
- So where should we put main? When java first came out, it was common to create all your classes that you might need, and select one and put main in that. That went well with the OOP philosophy that data is the most important (see how we're adding methods to data? the data comes first) but over time I see more and more that you create a special class that holds nothing but main(). This organizes the program better and makes more sense to beginning students. Since netbeans endorses it, I now consider it canon.
- Do we ever put main in other classes? Yes, all the time, we put testing code in the main of each class! We can spend a lot of time working on a class, but how do you know it works? Sometimes you have to wait for the rest of the program to be written to test it. But you could put testing code for that class in the main() in that class, so you can try it out before plugging into the rest of the program.