class Pendulum { ... void resetEverything( ) { mass = 1.0; length = 1.0; cycles = 0; ... float startingPosition = getPosition( 0.0 ); } ... }
Other classes access members of an object through a reference, using the (C-style) dot notation:
class TextBook { ... void showPendulum( ) { Pendulum bob = new Pendulum( ); ... int i = bob.cycles; bob.resetEverything( ); bob.mass = 1.01; ... } ... }
Here we have created a second class, TextBook, that uses a Pendulum object. It creates an instance in showPendulum() and then invokes methods and accesses variables of the object through the reference bob.
Several factors affect whether class members can be accessed from "outside" the class (from another class). You can use the visibility modifiers public, private, and protected to control access; classes can also be placed into a package, which affects their scope. The private modifier, for example, designates a variable or method for use only by other members of the class itself. In the previous example, we could change the declaration of our variable cycles to private:
class Pendulum { ... private int cycles; ...
Now we can't access cycles from TextBook:
class TextBook { ... void showPendulum( ) { ... int i = bob.cycles; // Compile time error
If we still need to access cycles in some capacity, we might add a public getCycles() method to the Pendulum class. We'll take a detailed look at packages, access modifiers, and how they affect the visibility of variables and methods in Chapter 6.
5.1.2 Static Members
As we've said, instance variables and methods are associated with and accessed through an instance of the class—i.e., through a particular object. In contrast, members that are declared with the static modifier live in the class and are shared by all instances of the class. Variables declared with the static modifier are called static variables or class variables; similarly, these kinds of methods are called static methods or class methods. We can add a static variable to our Pendulum example:
class Pendulum { ... static float gravAccel = 9.80; ...
We have declared the new float variable gravAccel as static. That means if we change its value in any instance of a Pendulum, the value changes for all Pendulum objects, as shown in Figure 5-2.
Figure 5-2. Static variables shared by all instances of a class
Static members can be accessed like instance members. Inside our Pendulum class, we can refer to gravAccel, like an instance variable:
class Pendulum { ... float getWeight ( ) { return mass * gravAccel; } ... }
However, since static members exist in the class itself, independent of any instance, we can also access them directly through the class. We don't need a Pendulum object to set the variable gravAccel; instead we can use the class name in place of a reference-type variable:
Pendulum.gravAccel = 8.76;
This changes the value of gravAccel for any current or future instances. Why would we want to change the value of gravAccel? Well, perhaps we want to explore how pendulums would work on different planets. Static variables are also very useful for other kinds of data shared among classes at runtime. For instance, you can create methods to register your objects so that they can communicate, or you can keep track of references to them. It's also common to use static variables to define constant values. In this case, we use the static modifier along with the final modifier. So, if we cared only about pendulums under the influence of the Earth's gravitational pull, we could change Pendulum as follows:
class Pendulum { ... static final float EARTH_G = 9.80; ...
We have followed a common convention and named our constant with capital letters. Now the value of EARTH_G is a constant; it can be accessed by any instance of Pendulum (or anywhere, for that matter), but its value can't be changed at runtime.
It's important to use the combination of static and final only for things that are really constant. That's because the compiler is allowed to "inline" such values within classes that reference them. This means that if you change a static final variable you may have to recompile all code that uses that class (this is really the only case where you have to do that in Java). Static members are useful as flags and identifiers, which can be accessed from anywhere. They are especially useful for values needed in the construction of an instance itself. In our example, we might declare a number of static values to represent various kinds of Pendulum objects:
class Pendulum { ... static int SIMPLE = 0, ONE_SPRING = 1, TWO_SPRING = 2; ...
We might then use these flags in a method that sets the type of a Pendulum or, more likely, in a special constructor, as we'll discuss shortly:
Pendulum pendy = new Pendulum( ); pendy.setType( Pendulum.ONE_SPRING );
Again, inside the Pendulum class, we can use static members directly by name, as well; there's no need for the Pendulum. prefix:
class Pendulum { ... void resetEverything( ) { setType ( SIMPLE ); ... } ... }
No comments:
Post a Comment