Certification Objective Statics (Exam Objective 1.3)


Certification Objective —Statics (Exam Objective 1.3)

1.3 Develop code that declares, initializes, and uses primitives, arrays, enums, and objects as static, instance, and local variables. Also, use legal identifiers for variable names.

Static Variables and Methods

The static modifier has such a profound impact on the behavior of a method or variable that we're treating it as a concept entirely separate from the other modifiers. To understand the way a static member works, we'll look first at a reason for using one. Imagine you've got a utility class with a method that always runs the same way; its sole function is to return, say, a random number. It wouldn't matter which instance of the class performed the method—it would always behave exactly the same way. In other words, the method's behavior has no dependency on the state (instance variable values) of an object. So why, then, do you need an object when the method will never be instance-specific? Why not just ask the class itself to run the method?

Let's imagine another scenario: Suppose you want to keep a running count of all instances instantiated from a particular class. Where do you actually keep that variable? It won't work to keep it as an instance variable within the class whose instances you're tracking, because the count will just be initialized back to a default value with each new instance. The answer to both the utility-method-always-runs-the-same scenario and the keep-a-running-total-of-instances scenario is to use the static modifier. Variables and methods marked static belong to the class, rather than to any particular instance. In fact, you can use a static method or variable without having any instances of that class at all. You need only have the class available to be able to invoke a static method or access a static variable. static variables, too, can be accessed without having an instance of a class. But if there are instances, a static variable of a class will be shared by all instances of that class; there is only one copy.

The following code declares and uses a static counter variable:

 class Frog {    static int frogCount = 0;  // Declare and initialize                               // static variable    public Frog() {       frogCount += 1;  // Modify the value in the constructor    }    public static void main (String [] args) {       new Frog();       new Frog();       new Frog();       System.out.println ("Frog count is now " + frogCount);    }  } 

In the preceding code, the static frogCount variable is set to zero when the Frog class is first loaded by the JVM, before any Frog instances are created! (By the way, you don't actually need to initialize a static variable to zero; static variables get the same default values instance variables get.) Whenever a Frog instance is created, the Frog constructor runs and increments the static frogCount variable. When this code executes, three Frog instances are created in main(), and the result is

 Frog count is now 3 

Now imagine what would happen if frogCount were an instance variable (in other words, nonstatic):

 class Frog {    int frogCount = 0;  // Declare and initialize                        // instance variable    public Frog() {       frogCount += 1;  // Modify the value in the constructor    }    public static void main (String [] args) {       new Frog();       new Frog();       new Frog();       System.out.println ("Frog count is now " + frogCount);    } } 

When this code executes, it should still create three Frog instances in main() , but the result isa compiler error! We can't get this code to compile, let alone run.

 Frog.java:11: non-static variable frogCount cannot be referenced from a static context     System.out.println("Frog count is " + frogCount);                                           ^     1 error 

The JVM doesn't know which Frog object's frogCount you're trying to access. The problem is that main() is itself a static method, and thus isn't running against any particular instance of the class, rather just on the class itself. A static method can't access a nonstatic (instance) variable, because there is no instance! That's not to say there aren't instances of the class alive on the heap, but rather that even if there are, the static method doesn't know anything about them. The same applies to instance methods; a static method can't directly invoke a nonstatic method. Think static = class, nonstatic = instance. Making the method called by the JVM (main()) a static method means the JVM doesn't have to create an instance of your class just to start running code.

image from book
Exam Watch

One of the mistakes most often made by new Java programmers is attempting to access an instance variable (which means nonstatic variable) from the static main() method (which doesn't know anything about any instances, so it can't access the variable). The following code is an example of illegal access of a nonstatic variable from a static method:

 class Foo {     int x = 3;     public static void main (String [] args) {        System.out.println("x is " + x); }   } 

Understand that this code will never compile, because you can't access a nonstatic (instance) variable from a static method. Just think of the compiler saying, "Hey, I have no idea which Foo object's x variable you're trying to print!" Remember, it's the class running the main() method, not an instance of the class.

Of course, the tricky part for the exam is that the question won't look as obvious as the preceding code. The problem you're being tested for—accessing a nonstatic variable from a static method—will be buried in code that might appear to be testing something else. For example, the preceding code would be more likely to appear as

 Class Foo {     int x = 3;     float y = 4.3f;     public static void main (String [] args) {        for (int z = x; z < ++x; z--, y = y + z) {           // complicated looping and branching code       } } 

So while you're trying to follow the logic, the real issue is that x and y can't be used within main(), because x and y are instance, not static, voriablesl The same applies for accessing nonstatic methods from a static method. The rule is, a static method of a class can't access a nonstatic (instance) method or variable o f its own class.

image from book

Accessing Static Methods and Variables

Since you don't need to have an instance in order to invoke a static method or access a static variable, then how do you invoke or use a static member? What's the syntax? We know that with a regular old instance method, you use the dot operator on a reference to an instance:

 class Frog {    int frogSize = 0;    public int getFrogSize() {       return frogSize;    }    public Frog(int s)       frogSize = s;    }    public static void main (String [] args) {       Frog f = new Frog (25);       System.out.println (f.getFrogSize()); // Access instance                                             // method using f    } } 

In the preceding code, we instantiate a Frog, assign it to the reference variable f, and then use that f reference to invoke a method on the Frog instance we just created. In other words, the getFrogsize() method is being invoked on a specific Frog object on the heap.

But this approach (using a reference to an object) isn't appropriate for accessing a static method, because there might not be any instances of the class at all! So, the way we access a static method (or static variable) is to use the dot operator on the class name, as opposed to using it on a reference to an instance, as follows:

 class Frog {    static int frogCount = 0;  // Declare and initialize                               // static variable    public Frog() {       frogCount += 1;  // Modify the value in the constructor    } } class TestFrog {    public static void main (String [] args) {       new Frog();      new Frog();      new Frog();      System.out.print("frogCount:"+Frog.frogCount); //Access                                               // static variable    } } 

But just to make it really confusing, the Java language also allows you to use an object reference variable to access a static member:

 Frog f = new Frog(); int frogs = f.frogCount;  // Access static variable                           // FrogCount using f 

In the preceding code, we instantiate a Frog, assign the new Frog object to the reference variable f, and then use the f reference to invoke a static method! But even though we are using a specific Frog instance to access the static method, the rules haven't changed. This is merely a syntax trick to let you use an object reference variable (but not the object it refers to) to get to a static method or variable, but the static member is still unaware of the particular instance used to invoke the static member. In the Frog example, the compiler knows that, the reference variable f is of type Frog, and so the Frog class static method is run with no awareness or concern for the Frog instance at the other end of the f reference. In other words, the compiler cares only that reference variable f is declared as type Frog. Figure 2-8 illustrates the effects of the static modifier on methods and variables.

image from book
Figure 2-8: The effects of static on methods and variables

Finally, remember that static methods can't be overridden! This doesn't mean they can't be redefined in a subclass, but redefining and overriding aren't the same thing. Let's take a look at an example of a redefined (remember, not overridden), static method:

 class Animal {   static void dostuff() {     System.out.print("a ");   } } class Dog extends Animal {   static void dostuff() {         // it's a redefinition,                                    // not an override     System.out.print("d ");   }   public static void main (String [] args) {     Animal [] a = {new Animal(), new Dog(), new Animal()};     for (int x = 0; x < a.length; x++)       a[x].doStuff();                // invoke the static method   } } 

Running this code produces the output:

 a a a 

Remember, the syntax a[x].dostuff() is just a shortcut (the syntax trick)the compiler is going to substitute something like Animal.dostuff() instead. Notice that we didn't use the Java 1.5 enhanced for loop here (covered in Chapter 5), even though we could have. Expect to see a mix of both Java 1.4 and Java 5 coding styles and practices on the exam.




SCJP Sun Certified Programmer for Java 5 Study Guide Exam 310-055
SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055) (Certification Press)
ISBN: 0072253606
EAN: 2147483647
Year: 2006
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net