Preface
This lesson is one of a series of lessons designed to teach you about the essence of Object-Oriented Programming (OOP) using Java. The first lesson in the group was entitled The Essence of OOP Using Java, Objects, and Encapsulation. That lesson, and each of the lessons following that one, has provided explanations of certain aspects of the essence of Object-Oriented Programming using Java. The previous lesson was entitled The Essence of OOP using Java, Polymorphism and Interfaces, Part 2.
Necessary and significant aspectsThis miniseries will describe and discuss the necessary and significant aspects of OOP using Java. If you have a general understanding of computer programming, you should be able to read and understand the lessons in this miniseries, even if you don't have a strong background in the Java programming language.
Supplementary materialI recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at Baldwin's Java Programming Tutorials.
Preview
Static membersThere is another aspect of OOP in Java that I have avoided up to this point in the discussion: static variables and static methods.
Tends to complicate ...I have avoided this topic because, while not particularly difficult, the existence of static members tends to break up the simple structures that I have discussed in previous lessons in this miniseries.
While static members can be useful in some situations, the existence of static members tends to complicate the overall object-oriented structure of Java.
Avoid overuse of static membersFurthermore, the overuse of static members can lead to problems similar to those experienced in languages like C and C++ that support global variables and global functions.
When to use static membersI will discuss the use of static members in this lesson, and will provide some guidelines for their use.
The class named ClassI will also introduce the class named
Classand discuss how it enters into the use of static variables and methods.
Instance members vs.. class membersI will describe the differences between instance members and class members with particular emphasis being placed on their accessibility.
Three kinds of objectsFrom a conceptual viewpoint, there are at least three kinds of objects involved in a Java program:
- Ordinary objects
- Array objects
- Class objects
All of the discussion up to this point in the miniseries deals with what I have referred to in the above list as ordinary objects.
These are the objects that you instantiate in you code by applying the
newoperator to a constructor for a class in order to create a new instance (object) of that class. (There are also a couple of other ways to create ordinary objects, but I'm not going to get into that at this time.)
Array objectsI haven't discussed array objects thus far in this miniseries. (I plan to discuss them in a subsequent lesson.)
Suffice it for now to say that Array objects are objects whose purpose is to encapsulate a one-dimensional array structure that can contain either primitive values, or references to other objects (including other Array objects).
I will discuss Class objects in this lesson.
Discussion and Sample Code
Class objectsLet me emphasize at the beginning that the following discussion is
conceptualin nature. In this discussion, I will describe how the Java system behaves, not how it is implemented. In other words, however it is implemented, it behaves as though it is implemented as described below.
The class named ClassThere is a class whose name is
Class. The purpose of this class is to encapsulate information about some other class (actually, it can also be used to encapsulate information about primitive types as well as class types).
Here is part of what Sun has to say about this class:
"Instances of the class Class represent classes and interfaces in a running Java application. ... Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded ..."What does this mean?
As a practical matter, when one or more objects are instantiated from a given class, an extra object of the
Classclass is also instantiated automatically. This object contains information about the class from which the objects were instantiated.
(Note that it is also possible to cause a Class object that describes a specific class to be created in the absence of objects of that class, but that is a topic that will be reserved for more advanced lessons.)A real-world analogy
Here is an attempt to describe a real-world analogy. Remember that a class definition contains the blueprint for objects instantiated from that class.
A certain large construction company is in the business of building condominium projects. This contractor builds condos of many different sizes, types, and price ranges. However, each different condo project contains condos of only two or three different types or price ranges.
A library of blueprintsThere is a large library of blueprints at the contractor's central office. This library contains blueprints for all of the different types of condos that the contractor has built or is building. (This library is analogous to the class libraries available to the Java programmer.)
A subset from the blueprint libraryWhen a condo project begins, the contractor delivers copies of several sets of blueprints to the construction site. The blueprints delivered to that site describe only the types of condos being constructed on that site.
Condo is analogous to an objectEach condo unit is analogous to an ordinary Java object.
Each set of blueprints delivered to the construction site is roughly analogous to an object of the class named
Class. In other words, each set of blueprints describes one or more condo units constructed from that set of blueprints.
When construction is completeWhen the construction project is complete, the contractor delivers a set of blueprints for each type of condo unit to the management firm that has been hired to manage the condo complex. Each set of blueprints continues to be analogous to an object of the class named
Class. The blueprints remain at the site of the condo units.
RTTIThus, information regarding the construction, wiring, plumbing, air conditioning, etc., for each condo unit (object) continues to be available at the site even after the construction has been completed.
(This is somewhat analogous to something called runtime type information and often abbreviated as RTTI. A Class object contains RTTI for objects instantiated from that class.)What are those analogies again?
In the above scenario, each condo unit is (roughly) analogous to an object instantiated from a specific class (set of blueprints).
Each set of blueprints remaining onsite after construction is complete is roughly analogous to a
Classobject that describes the characteristics of one or more condo units.
What do you care?Until you get involved in such advanced topics as reflection and introspection, you don't usually have much involvement or much interest in
Classobjects. They are created automatically, and are primarily used by the Java virtual machine during runtime to help it do the things that it needs to do.
An exception to that ruleHowever, there is one area where you will be interested in the use of these
Classobjects from early on. You will be interested whenever variables or methods in the class definition are declared to be
static.
Class variables and methodsAccording to the current jargon, declaring a member variable to be
staticcauses it to be a class variable.
(Note that local variables cannot be declared static . Only member variables can be declared static .)
Similarly, declaring a method to be
staticcauses it to be a class method.
Instance variables and methodsOn the other hand, according to the current jargon, not declaring a variable to be
staticcauses it to be an instance variable, and not declaring a method to be
staticcauses it to be an instance method.
In general, we can refer to them as class members and instance members.
What is the difference?Here are some of the differences between class and instance members insofar as this discussion is concerned.
How many copies of member variables exist?Every object instantiated from a given class has its own copy of each instance variable defined in the class.
(Instance variables are not shared among objects.)
However, every object instantiated from a given class shares the same copy of each class variable defined in the class.
(It is as though the class variable belongs to the single Class object and not to the individual objects instantiated from that class.)Access to an instance variable
Every object has its own copy of each instance variable (the object owns the instance variable). Therefore, the only way that you can access an instance variable is to use that object's reference to send a message to the object requesting access to the variable (even then, you may not be given access, depending on access modifiers).
Why call it an instance variable?According to the current jargon,
an object is an instance of a class.
(I probably told you that somewhere before in this miniseries. At least, I hope that I did. After writing eight or ten lessons in a miniseries, I sometimes forget what I told you before.)
Each object has its own copy of each non-static variable. Hence, they are often called instance variables. (Every instance of the class has one.)
Access to a class variableYou can also send a message to an object requesting access to a class variable that the object shares with other objects instantiated from the same class. (Again, you may or may not gain access, depending the access modifiers).
Access using the Class objectMore importantly, you can also access a class variable without a requirement to go through an object instantiated from the class. (In fact, a class variable can be accessed in the total absence of objects of that class.)
(Remember, this discussion is conceptual in nature, and may not represent an actual implementation.)
Assuming that a class variable is otherwise accessible, you can access the class variable by sending an access request message to the
Classobject to which the variable belongs.
One way to think of thisTo help you keep track of thing in a message-passing sense, you can pretend that there is a global reference variable whose name is the same as the name of a class.
This (hypothetical) reference variable contains a reference to the
Classobject that owns the class variable. Using standard Java message-passing syntax, you can access the class variable by joining the name of the reference variable to the name of the class variable with a period. Example syntax is shown below:
ReferenceVariableName.ClassVariableNameAs a result of the hypothetical substitution process that I described above, this is equivalent to the following:
ClassName.ClassVariableNameWe will see an example of this in the sample program that I will discuss later.
Be careful with this thought process While this thought process may be useful when thinking about static variables and methods, I want to point out, that the thought process breaks down very quickly when dealing with ClassCharacteristics of class methodsobjects in a deeper sense.
For example, when invoking the
getName method on a Class object, an actual reference of type Class is required to access the members of the Classobject. The name of the class will not suffice.
If this discussion of a global reference variable whose name matches the name of the class is confusing to you, just forget it. Simply remember that you can access class variables by joining the name of the class to the name of the class variable using a period as the joining operator.
I'm not going to talk very much about instance methods and class methods in this lesson. However, there are a couple of characteristics of class methods that deserve a brief discussion in this context.
Cannot access instance membersFirst, the code in a class method has direct access only to other
staticmembers of the class.
(A class method does not have direct access to instance variables or instance methods of the class.)
This is sort of like saying that a class method has access to the methods and variables belonging to the
Classobject, but does not have access to the methods and variables belonging to the ordinary objects instantiated from the class described by the
Classobject.
Once again, be careful Once again, this thinking breaks down very quickly once you get beyond static members. A Class object also has instance methods, such as getName , which can only be accessed using an actual reference to the ClassNo object requiredobject.
Now you are probably beginning to understand why I deferred this discussion until after I finished discussing the easy stuff.
Another important characteristic is that a class method can be accessed without a requirement for an object of the class to exist.
As with class variables, class methods can be accessed by joining the name of the class to the name of the method with a period.
I will illustrate much of this with a sample program named
MyClass01.
Discuss in fragmentsI will discuss the program in fragments. You will find a complete listing of the program in Listing 13 near the end of the lesson.
Listing 1 shows the beginning of the class definition.
|
The code in Listing 1 declares two member variables, named
v1and
v2, and initializes each of those variables with a reference to a new object of the
Dateclass.
(When instantiated using the constructor with no arguments, the new Date object encapsulates the current date and time from the system clock.)Note the static keyword
The important thing to note here is the use of the
statickeyword when declaring the variable named
v1. This causes
v1to be a class variable, exhibiting the characteristics of class variables described earlier.
An instance variableOn the other hand, the variable named
v2is not declared
static. This causes it to be an instance variable, as described above.
The main method is a class methodListing 2 shows the signature for the
mainmethod.
|
The important thing to note here is that the
mainmethod is declared
static. That causes it to be a class method.
As a result, the
mainmethod can be invoked without a requirement for an object of the class to exist.
(Also, the main method has direct access only to other static members.)How a Java application starts running
In fact, that is how the Java Virtual Machine starts an application running.
First the JVM finds the specified file having an extension of
.class.Then it examines that file to see if it has a
mainmethod with the correct signature. If not, an error occurs.
If the JVM finds a
mainmethod with the correct signature, it invokes that method without instantiating an object of the class. That is how the Java Virtual Machine causes a Java application to start running.
A side note regarding applets For those of you who are familiar with Java applets, you should know that this is not the case for an applet. You should know that an applet does not use a main method. When an applet is started, an object of the controlling class is instantiated by the browser, by the appletviewer program, or by whatever program is being used to control the execution of the applet.A poor programming technique
Basically, this entire sample program is coded inside the
mainmethod. As a practical manner, that is a very poor programming technique, but it works well for this example.
Display some textThe code in Listing 3, which is the first executable statement in the
mainmethod, causes the words
Static variableto appear on the computer screen. I will come back and discuss the details of this and similar statements later in the lesson.
|
Proceeding down through the code in the
mainmethod, the code in Listing 4 causes the current contents of the
Dateobject referred to by the contents of the class variable named
v1to be displayed on the computer screen.
|
For the moment, concentrate on the boldface text in the statement in Listing 4.
IMPORTANT:Because the variable named
v1is a class variable, it's value is accessed by joining the name of the class to the name of the variable with a period.
What was the output?I will also discuss the remaining portion of statements of this sort later. For now, just be aware that it caused the output shown in Figure 1 to be displayed on my computer screen when I ran the program.
|
Obviously, the date and time displayed will depend on when you run the program.
Pay particular attention to the seconds portion of the time. I will refer back to this later.
A five-second delayThe code in Listing 5 (still in the
mainmethod) causes the main thread of the program to go to sleep for five seconds. Don't worry about it if you don't understand this code. The only reason that I included it in the program was to force a five-second delay in the execution of the program.
|
Having caused the program to sleep for five seconds, the code in Listing 6 instantiates a new object of the class named
MyClass01. The code stores the new object's reference in the reference variable named
ref1.
|
Recall from Listing 1 above that the class declares an instance variable named
v2of the type
Date.
When the new object is instantiated by the code in Listing 6, a new
Dateobject is also instantiated. A reference to that object is stored in the instance variable named
v2.
(In other words, the new object of the class MyClass01 owns a reference to a new object of the class Date . That reference is stored in an instance variable named v2 in the new MyClass01 object.)Display the new Date object
The code in Listing 7 causes a textual representation of the new
Dateobject referred to by the reference variable named
v2belonging to the object referred to by the reference variable named
ref1, to be displayed on the standard output device.
|
This code caused the date and time shown in Figure 2 to appear on the computer screen when I ran the program:
|
If you note the time in the above output, you will see that it is five seconds later than the time reflected in the
Dateobject referred to by the class variable named
v1. That time was displayed by the code in Listing 4 earlier.
So, what does this mean?It means that the
Dateobject referred to by the
staticreference variable named
v1was created five seconds earlier than the
Dateobject referred to by the instance variable named
v2.
When is a class variable created?I can't tell you precisely when a class variable comes into existence. All I can say is that the virtual machine brings it into existence as soon as it is needed.
My guess is that it comes into existence at the first mention (in the program) of the class to which it belongs.
When is an instance variable created?An instance variable doesn't come into existence until the object to which it belongs is created (an instance variable cannot exist until the object to which it belongs exists).
If the instance variable is initialized with a reference to a new object (such as a new Date object in this sample program), that new object comes into existence when the object to which it belongs comes into existence.
A five-second delayIn this program, I purposely inserted a five-second delay between the first mention of the class named
MyClass01in Listing 4, and the instantiation of the object of the class named
MyClass01in Listing 6.
As a result, the
Dateobject referred to by the instance variable named
v2was created about five seconds later than the
Dateobject referred to by the class variable named
v1.
This is reflected in the date and time values displayed and discussed earlier.
Accessing class variable via an objectWhile it is possible to access a class variable using the name of the class joined to the name of the variable, it is also possible to access a class variable using a reference to any object instantiated from the class.
(As mentioned earlier, if two or more objects are instantiated from the same class, they share the same class variable.)
The boldface code in Listing 8 uses the reference variable named
ref1to access the class variable named
v1, and to cause the contents of the
Dateobject referred to by the class variable to be displayed.
|
This caused the date and time shown in Figure 3 to be displayed on my computer screen.
|
As you have probably already surmised, this is the same date and time shown earlier in Figure 1. This is because the code in Listing 8 refers to the same class variable as the code in Listing 4. Nothing has caused the contents of that class variable to change, so both Figure 1 and Figure 3 display the contents of the same
Dateobject.
(Only one class variable exists and it doesn't matter how you access it. Either way, you gain access to the same Date object whose reference is stored in the class variable. Thus, the same date and time is shown in both cases.)Another new object
If you examine the code in Listing 13 near the end of the program, you will see that an additional five-second delay is introduced at this point in the program.
Following that delay, the code in Listing 9 instantiates another new object of the class named
MyClass01, and stores the object's reference in a new reference variable named
ref2.
(The object referred to by ref1 is a different object than the object referred to by ref2 . Each object has its own instance variable named v2 , and in this case, each instance variable is initialized to instantiate and refer to a new Date object when the new MyClass01 object is instantiated.)
|
Then, the code in Listing 10 causes the contents of the
Dateobject referred to by the instance variable named
v2in the second object of the class named
MyClass01to be displayed.
|
This caused the output shown in Figure 4 to be displayed on my computer screen when I ran the program (again, you will get different results if you compile and run the program because the date and time shown is the date and time that you run the program).
|
As you have probably figured out by now, the time encapsulated in this
Dateobject is five seconds later than the time encapsulated in the
Dateobject displayed in Figure 2. This is because the program was put to sleep for five seconds between the instantiation of the two objects referred to by
ref1and
ref2.
Every object has oneEvery object instantiated from a given class has its own copy of each instance variable declared in the class definition. There is no sharing of instance variables among objects.
Each instance variable comes into existence when the object to which it belongs comes into existence, and ceases to exist when the object to which it belongs ceases to exist.
(If the instance variables are reference variables holding references to other objects, as is the case here, and if there are no other reference variables holding references to those same objects, the secondary objects cease to exist when the primary objects cease to exist. Technically, the objects may not cease to exist. Technically they become eligible for garbage collection, which means that the memory that they occupy becomes eligible for reuse. However, as a practical matter, they cease to exist insofar as the program is concerned. They are no longer accessible.)
Since the two objects referred to by
ref1and
ref2came into existence with a five-second delay, the
Dateobjects belonging to those two object reflect a five-second difference in the time encapsulated in the objects.
Only one copy of class variable existsAlso remember that if a variable is a class variable, only one copy of the variable exists, and all objects instantiated from the class share that one copy.
This is illustrated by the code in Listing 11, which uses the reference to the second object instantiated from the class named
MyClass01, to cause the contents of the class variable named
v1to be displayed.
|
The output produced by the code in Listing 11 is shown in Figure 5.
|
As you can see, this is the same as the output shown in Figure 1 and Figure 3 earlier.
Accessing the same physical class variableSince only one class variable named
v1exists, and all objects instantiated from the class named
MyClass01share that single copy, it doesn't matter whether you access the class variable using the name of the class, or access it using a reference to either of the objects instantiated from the class. In all three cases, you are accessing the same physical class variable.
Since nothing was done to cause the contents of the class variable to change after it came into existence and was initialized, Figures 1, 3, and 5 are simply three different displays of the date and time encapsulated in the same
Dateobject whose reference is stored in the class variable.
Let's revisit System.out.println...Now, I want to revisit the statement originally shown in Listing 8 and repeated in Listing 12 for viewing convenience.
|
I often tell my students that if I were out in industry, interviewing prospective Java programmers, my first question would be to ask the prospective employee to tell me everything that she knows about the statement in Listing 12.
Covers a lot of Java OOP technologyThis is not because there is a great demand for the use of this statement in real-world problems. (In fact, in a GUI-driven software product world, there is probably very little demand for the use of this statement.) Rather, it is because a lot of Java object-oriented technology is embodied in this single statement.
In that scenario, I would expect to receive a verbal dissertation of fifteen to twenty minutes in length to cover all the important points.
The short versionLet me give you the short version. There is a class named
System. The
Systemclass declares three
static(class) variables having the following types, names, and modifiers:
- public static final PrintStream out
- public static final InputStream in
- public static final PrintStream err
(Note that these class variables are also declared final , causing them to behave as constants.)Access the out variable without an object
Because
outis a class variable,
System.outreturns the contents of the class variable named
out(an object of the System class is not required in order to access a class variable of the System class).
In general, (ignoring the possibility of subclasses and interfaces) because
outis a reference variable of type
PrintStream, the returned value must either be
null(no object reference) or a reference to a valid
PrintStreamobject.
Object of the PrintStream classWhen the Java Virtual Machine starts an application running, it instantiates an object of the
PrintStreamclass and connects it to the
standard output device.
(By default, the standard output device is typically the computer screen, but it can be redirected at the operating system level to be some other device. The following discussion assumes that the screen is the standard output device.)Assign object's reference to out variable
When the
PrintStreamobject is instantiated by the virtual machine, the object's reference is assigned to the class variable of the
Systemclass named
out.
(Because the variable named out is final, the contents of the variable cannot be modified later.)Reference to a PrintStream object
Therefore, the expression
System.outreturns a reference to the
PrintStreamobject, which is connected to the standard output device.
Many instance methodsAn object of the
PrintStreamclass contains many instance methods. This includes numerous overloaded versions of a method named
println. The signature of one of those overloaded versions of the
printlnmethod follows:
public void println(Object x) Textual representation of an objectThe purpose of this overloaded version of the
printlnmethod is to:
- Create a textual representation of the object referred to by the incoming parameter of type Object (because Object is a totally generic type, this version of the println method can accept an incoming parameter that is a reference to any type of object)
- Send that textual representation to the output device
In general ... (In general, a new PrintStream object can be connected to a variety of output devices when it is instantiated. However, in the special case of the PrintStream object instantiated by the virtual machine when the program starts, whose reference is stored in the class variable named out of the System class, the purpose of the object is to provide a display path to the standard output device.)Our old friend, the toString method
To accomplish this, the code in the
printlnmethod invokes the
toStringmethod on the incoming reference.
(I discussed the toString method in detail in earlier lessons in this miniseries.)
The
toStringmethod may, or may not, have been overridden in the definition of the class from which the object was instantiated, or in some superclass of the class from which the object was instantiated.
Default version of toStringIf not overridden, the default version of the
toStringmethod defined in the
Objectclass is used to produce a textual representation of the object. As we learned in an earlier lesson, that textual representation looks something like the following:
[email protected] Overridden version of toString methodIf the class from which the object was instantiated (or some superclass of that class) contains an overridden version of the
toStringmethod, runtime polymorphism kicks in and the overridden version of the method is executed to produce the textual representation of the object.
The Date class overrides toStringIn the case of this sample program, the object was instantiated from the
Dateclass. The
Dateclass does override the
toStringmethod.
When the overridden
toStringmethod is invoked on a
Dateobject's reference, the
Stringreturned by the method looks something like that shown in Figure 6.
|
You will recall that this is the output that was produced by the code shown in Listing 8 and Listing 12.
More than you ever wanted to know ...And that is probably more than you ever wanted to know about the expression
System.out.println....
It is also probably more than you ever wanted to know about class variables, class methods, instance variables, and instance methods.
Some cautionsBefore leaving this topic, I do want to express some cautions. Basically, I want to suggest that you use static members very sparingly, if at all. Several good sets of guidelines have been published regarding the use of static members. As of this writing, you can find one of them, written by Mark L. Fussell, at the following URL.
Guidelines for use of static membersI will try to summarize the general sense of most published guidelines in a few words.
Static variablesTo begin with, don't ever use static variables without declaring them
finalunless you understand exactly why you are declaring them static.
(Static final variables, or constants, are often very appropriate. See the fields in the Color class for example.)
I can only think of a few situations where the use of a non-final static variable might be appropriate.
(One appropriate use might be to count the number of objects instantiated from a specific class. I suspect there are a few other appropriate uses as well.)Static methods
Don't declare methods static if there is any requirement for the method to remember anything from one invocation to the next.
There are many appropriate uses for static methods, but in most cases, the purpose of the method will be to completely perform some action with no requirement to remember anything from that invocation to the next.
The method should probably also be self-contained. By this I mean that all information that the method needs to do its job should either come from incoming parameters or from final static member variables (constants). The method probably should not depend on the values stored in non-final static member variables, which are subject to change over time.
(A static method only has access to other static members of the class, so it cannot depend on instance variables defined in the class.)
An appropriate example of a static method is the
sqrtmethod of the
Mathclass. This method computes and "Returns the correctly rounded positive square root of a double" where the double value is provided as a parameter to the method. Each time the method is invoked, it completes its task and doesn't attempt to save any values from that invocation to the next. Furthermore, it gets all the information that it needs to do its job from an incoming parameter.
Summary
Added complexityThe existence of static members tends to break up the simple OOP structures that I have discussed in previous lessons in this miniseries.
While static members can be useful in some situations, the existence of static members tends to complicate the overall object-oriented structure of Java.
Furthermore, the overuse of static members can lead to problems similar to those experienced in languages like C and C++ that support global variables and global functions.
The class named ClassI discussed the class named
Classand how a conceptual object of type
Classexists in memory following a reference to a specific class in the program code.
The
Classobject represents the referenced class in memory, and contains the static variables and static methods belonging to that class. (It contains some other information as well, such as the name of the superclass.)
Class members and instance membersClass variables and class methods are declared static (declaring a member static in the class definition causes to be called a class member).
Instance variables and instance methods are not declared static.
Each object has its own copy ...Every object instantiated from a given class has its own copy of each instance variable declared in the class definition. (Instance variables are not shared among objects.)
Every object instantiated from a given class acts like it has its own copy of every instance method declared in the class definition. (Although instance methods are actually shared among objects in order to reduce the amount of memory required, they are shared in such a way that they don't appear to be shared.)
Every object shares ...Every object instantiated from a given class shares the same single copy of each class variable declared in the class definition. Similarly, every object instantiated from a given class shares the same copy of each class method.
Accessing an instance memberAn instance variable or an instance method can only be accessed by using a reference to the object that owns it. Even then, it may or may not be accessible depending on the access modifier assigned by the programmer.
Accessing a class memberThe single shared copy of a class variable or a class method can be accessed in either of two ways:
- Via a reference to any object instantiated from the class
- By simply joining the name of the class to the name of the class variable or the class method
Again, the variable or method may or may not be accessible, depending on the access modifiers assigned by the programmer.
When to use class variablesIt is very often appropriate to use final static variables, as constants in your programs. It is rarely, if ever, appropriate to use non-final static variables in your programs. The use of non-final static variables should definitely be minimized.
When to use static methodsIt is often appropriate to use static methods in your programs, provided there is no requirement for the method to remember anything from one invocation to the next. Static methods should be self-contained.
What's Next?
The next lesson in this miniseries will address the special case of Array Objects.
Complete Program Listing
A complete listing of the sample program is shown in Listing 13.
|
Preface
This lesson is one of a series of lessons designed to teach you about the essence of Object-Oriented Programming (OOP) using Java. The first lesson in the group was entitled The Essence of OOP Using Java, Objects, and Encapsulation. That lesson, and each of the lessons following that one, has provided explanations of certain aspects of the essence of Object-Oriented Programming using Java. The previous lesson was entitled The Essence of OOP using Java, Polymorphism and Interfaces, Part 2.
Necessary and significant aspectsThis miniseries will describe and discuss the necessary and significant aspects of OOP using Java. If you have a general understanding of computer programming, you should be able to read and understand the lessons in this miniseries, even if you don't have a strong background in the Java programming language.
Supplementary materialI recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at Baldwin's Java Programming Tutorials.
Preview
Static membersThere is another aspect of OOP in Java that I have avoided up to this point in the discussion: static variables and static methods.
Tends to complicate ...I have avoided this topic because, while not particularly difficult, the existence of static members tends to break up the simple structures that I have discussed in previous lessons in this miniseries.
While static members can be useful in some situations, the existence of static members tends to complicate the overall object-oriented structure of Java.
Avoid overuse of static membersFurthermore, the overuse of static members can lead to problems similar to those experienced in languages like C and C++ that support global variables and global functions.
When to use static membersI will discuss the use of static members in this lesson, and will provide some guidelines for their use.
The class named ClassI will also introduce the class named
Classand discuss how it enters into the use of static variables and methods.
Instance members vs.. class membersI will describe the differences between instance members and class members with particular emphasis being placed on their accessibility.
Three kinds of objectsFrom a conceptual viewpoint, there are at least three kinds of objects involved in a Java program:
- Ordinary objects
- Array objects
- Class objects
All of the discussion up to this point in the miniseries deals with what I have referred to in the above list as ordinary objects.
These are the objects that you instantiate in you code by applying the
newoperator to a constructor for a class in order to create a new instance (object) of that class. (There are also a couple of other ways to create ordinary objects, but I'm not going to get into that at this time.)
Array objectsI haven't discussed array objects thus far in this miniseries. (I plan to discuss them in a subsequent lesson.)
Suffice it for now to say that Array objects are objects whose purpose is to encapsulate a one-dimensional array structure that can contain either primitive values, or references to other objects (including other Array objects).
I will discuss Class objects in this lesson.
Discussion and Sample Code
Class objectsLet me emphasize at the beginning that the following discussion is
conceptualin nature. In this discussion, I will describe how the Java system behaves, not how it is implemented. In other words, however it is implemented, it behaves as though it is implemented as described below.
The class named ClassThere is a class whose name is
Class. The purpose of this class is to encapsulate information about some other class (actually, it can also be used to encapsulate information about primitive types as well as class types).
Here is part of what Sun has to say about this class:
"Instances of the class Class represent classes and interfaces in a running Java application. ... Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded ..."What does this mean?
As a practical matter, when one or more objects are instantiated from a given class, an extra object of the
Classclass is also instantiated automatically. This object contains information about the class from which the objects were instantiated.
(Note that it is also possible to cause a Class object that describes a specific class to be created in the absence of objects of that class, but that is a topic that will be reserved for more advanced lessons.)A real-world analogy
Here is an attempt to describe a real-world analogy. Remember that a class definition contains the blueprint for objects instantiated from that class.
A certain large construction company is in the business of building condominium projects. This contractor builds condos of many different sizes, types, and price ranges. However, each different condo project contains condos of only two or three different types or price ranges.
A library of blueprintsThere is a large library of blueprints at the contractor's central office. This library contains blueprints for all of the different types of condos that the contractor has built or is building. (This library is analogous to the class libraries available to the Java programmer.)
A subset from the blueprint libraryWhen a condo project begins, the contractor delivers copies of several sets of blueprints to the construction site. The blueprints delivered to that site describe only the types of condos being constructed on that site.
Condo is analogous to an objectEach condo unit is analogous to an ordinary Java object.
Each set of blueprints delivered to the construction site is roughly analogous to an object of the class named
Class. In other words, each set of blueprints describes one or more condo units constructed from that set of blueprints.
When construction is completeWhen the construction project is complete, the contractor delivers a set of blueprints for each type of condo unit to the management firm that has been hired to manage the condo complex. Each set of blueprints continues to be analogous to an object of the class named
Class. The blueprints remain at the site of the condo units.
RTTIThus, information regarding the construction, wiring, plumbing, air conditioning, etc., for each condo unit (object) continues to be available at the site even after the construction has been completed.
(This is somewhat analogous to something called runtime type information and often abbreviated as RTTI. A Class object contains RTTI for objects instantiated from that class.)What are those analogies again?
In the above scenario, each condo unit is (roughly) analogous to an object instantiated from a specific class (set of blueprints).
Each set of blueprints remaining onsite after construction is complete is roughly analogous to a
Classobject that describes the characteristics of one or more condo units.
What do you care?Until you get involved in such advanced topics as reflection and introspection, you don't usually have much involvement or much interest in
Classobjects. They are created automatically, and are primarily used by the Java virtual machine during runtime to help it do the things that it needs to do.
An exception to that ruleHowever, there is one area where you will be interested in the use of these
Classobjects from early on. You will be interested whenever variables or methods in the class definition are declared to be
static.
Class variables and methodsAccording to the current jargon, declaring a member variable to be
staticcauses it to be a class variable.
(Note that local variables cannot be declared static . Only member variables can be declared static .)
Similarly, declaring a method to be
staticcauses it to be a class method.
Instance variables and methodsOn the other hand, according to the current jargon, not declaring a variable to be
staticcauses it to be an instance variable, and not declaring a method to be
staticcauses it to be an instance method.
In general, we can refer to them as class members and instance members.
What is the difference?Here are some of the differences between class and instance members insofar as this discussion is concerned.
How many copies of member variables exist?Every object instantiated from a given class has its own copy of each instance variable defined in the class.
(Instance variables are not shared among objects.)
However, every object instantiated from a given class shares the same copy of each class variable defined in the class.
(It is as though the class variable belongs to the single Class object and not to the individual objects instantiated from that class.)Access to an instance variable
Every object has its own copy of each instance variable (the object owns the instance variable). Therefore, the only way that you can access an instance variable is to use that object's reference to send a message to the object requesting access to the variable (even then, you may not be given access, depending on access modifiers).
Why call it an instance variable?According to the current jargon,
an object is an instance of a class.
(I probably told you that somewhere before in this miniseries. At least, I hope that I did. After writing eight or ten lessons in a miniseries, I sometimes forget what I told you before.)
Each object has its own copy of each non-static variable. Hence, they are often called instance variables. (Every instance of the class has one.)
Access to a class variableYou can also send a message to an object requesting access to a class variable that the object shares with other objects instantiated from the same class. (Again, you may or may not gain access, depending the access modifiers).
Access using the Class objectMore importantly, you can also access a class variable without a requirement to go through an object instantiated from the class. (In fact, a class variable can be accessed in the total absence of objects of that class.)
(Remember, this discussion is conceptual in nature, and may not represent an actual implementation.)
Assuming that a class variable is otherwise accessible, you can access the class variable by sending an access request message to the
Classobject to which the variable belongs.
One way to think of thisTo help you keep track of thing in a message-passing sense, you can pretend that there is a global reference variable whose name is the same as the name of a class.
This (hypothetical) reference variable contains a reference to the
Classobject that owns the class variable. Using standard Java message-passing syntax, you can access the class variable by joining the name of the reference variable to the name of the class variable with a period. Example syntax is shown below:
ReferenceVariableName.ClassVariableNameAs a result of the hypothetical substitution process that I described above, this is equivalent to the following:
ClassName.ClassVariableNameWe will see an example of this in the sample program that I will discuss later.
Be careful with this thought process While this thought process may be useful when thinking about static variables and methods, I want to point out, that the thought process breaks down very quickly when dealing with ClassCharacteristics of class methodsobjects in a deeper sense.
For example, when invoking the
getName method on a Class object, an actual reference of type Class is required to access the members of the Classobject. The name of the class will not suffice.
If this discussion of a global reference variable whose name matches the name of the class is confusing to you, just forget it. Simply remember that you can access class variables by joining the name of the class to the name of the class variable using a period as the joining operator.
I'm not going to talk very much about instance methods and class methods in this lesson. However, there are a couple of characteristics of class methods that deserve a brief discussion in this context.
Cannot access instance membersFirst, the code in a class method has direct access only to other
staticmembers of the class.
(A class method does not have direct access to instance variables or instance methods of the class.)
This is sort of like saying that a class method has access to the methods and variables belonging to the
Classobject, but does not have access to the methods and variables belonging to the ordinary objects instantiated from the class described by the
Classobject.
Once again, be careful Once again, this thinking breaks down very quickly once you get beyond static members. A Class object also has instance methods, such as getName , which can only be accessed using an actual reference to the ClassNo object requiredobject.
Now you are probably beginning to understand why I deferred this discussion until after I finished discussing the easy stuff.
Another important characteristic is that a class method can be accessed without a requirement for an object of the class to exist.
As with class variables, class methods can be accessed by joining the name of the class to the name of the method with a period.
I will illustrate much of this with a sample program named
MyClass01.
Discuss in fragmentsI will discuss the program in fragments. You will find a complete listing of the program in Listing 13 near the end of the lesson.
Listing 1 shows the beginning of the class definition.
|
The code in Listing 1 declares two member variables, named
v1and
v2, and initializes each of those variables with a reference to a new object of the
Dateclass.
(When instantiated using the constructor with no arguments, the new Date object encapsulates the current date and time from the system clock.)Note the static keyword
The important thing to note here is the use of the
statickeyword when declaring the variable named
v1. This causes
v1to be a class variable, exhibiting the characteristics of class variables described earlier.
An instance variableOn the other hand, the variable named
v2is not declared
static. This causes it to be an instance variable, as described above.
The main method is a class methodListing 2 shows the signature for the
mainmethod.
|
The important thing to note here is that the
mainmethod is declared
static. That causes it to be a class method.
As a result, the
mainmethod can be invoked without a requirement for an object of the class to exist.
(Also, the main method has direct access only to other static members.)How a Java application starts running
In fact, that is how the Java Virtual Machine starts an application running.
First the JVM finds the specified file having an extension of
.class.Then it examines that file to see if it has a
mainmethod with the correct signature. If not, an error occurs.
If the JVM finds a
mainmethod with the correct signature, it invokes that method without instantiating an object of the class. That is how the Java Virtual Machine causes a Java application to start running.
A side note regarding applets For those of you who are familiar with Java applets, you should know that this is not the case for an applet. You should know that an applet does not use a main method. When an applet is started, an object of the controlling class is instantiated by the browser, by the appletviewer program, or by whatever program is being used to control the execution of the applet.A poor programming technique
Basically, this entire sample program is coded inside the
mainmethod. As a practical manner, that is a very poor programming technique, but it works well for this example.
Display some textThe code in Listing 3, which is the first executable statement in the
mainmethod, causes the words
Static variableto appear on the computer screen. I will come back and discuss the details of this and similar statements later in the lesson.
|
Proceeding down through the code in the
mainmethod, the code in Listing 4 causes the current contents of the
Dateobject referred to by the contents of the class variable named
v1to be displayed on the computer screen.
|
For the moment, concentrate on the boldface text in the statement in Listing 4.
IMPORTANT:Because the variable named
v1is a class variable, it's value is accessed by joining the name of the class to the name of the variable with a period.
What was the output?I will also discuss the remaining portion of statements of this sort later. For now, just be aware that it caused the output shown in Figure 1 to be displayed on my computer screen when I ran the program.
|
Obviously, the date and time displayed will depend on when you run the program.
Pay particular attention to the seconds portion of the time. I will refer back to this later.
A five-second delayThe code in Listing 5 (still in the
mainmethod) causes the main thread of the program to go to sleep for five seconds. Don't worry about it if you don't understand this code. The only reason that I included it in the program was to force a five-second delay in the execution of the program.
|
Having caused the program to sleep for five seconds, the code in Listing 6 instantiates a new object of the class named
MyClass01. The code stores the new object's reference in the reference variable named
ref1.
|
Recall from Listing 1 above that the class declares an instance variable named
v2of the type
Date.
When the new object is instantiated by the code in Listing 6, a new
Dateobject is also instantiated. A reference to that object is stored in the instance variable named
v2.
(In other words, the new object of the class MyClass01 owns a reference to a new object of the class Date . That reference is stored in an instance variable named v2 in the new MyClass01 object.)Display the new Date object
The code in Listing 7 causes a textual representation of the new
Dateobject referred to by the reference variable named
v2belonging to the object referred to by the reference variable named
ref1, to be displayed on the standard output device.
|
This code caused the date and time shown in Figure 2 to appear on the computer screen when I ran the program:
|
If you note the time in the above output, you will see that it is five seconds later than the time reflected in the
Dateobject referred to by the class variable named
v1. That time was displayed by the code in Listing 4 earlier.
So, what does this mean?It means that the
Dateobject referred to by the
staticreference variable named
v1was created five seconds earlier than the
Dateobject referred to by the instance variable named
v2.
When is a class variable created?I can't tell you precisely when a class variable comes into existence. All I can say is that the virtual machine brings it into existence as soon as it is needed.
My guess is that it comes into existence at the first mention (in the program) of the class to which it belongs.
When is an instance variable created?An instance variable doesn't come into existence until the object to which it belongs is created (an instance variable cannot exist until the object to which it belongs exists).
If the instance variable is initialized with a reference to a new object (such as a new Date object in this sample program), that new object comes into existence when the object to which it belongs comes into existence.
A five-second delayIn this program, I purposely inserted a five-second delay between the first mention of the class named
MyClass01in Listing 4, and the instantiation of the object of the class named
MyClass01in Listing 6.
As a result, the
Dateobject referred to by the instance variable named
v2was created about five seconds later than the
Dateobject referred to by the class variable named
v1.
This is reflected in the date and time values displayed and discussed earlier.
Accessing class variable via an objectWhile it is possible to access a class variable using the name of the class joined to the name of the variable, it is also possible to access a class variable using a reference to any object instantiated from the class.
(As mentioned earlier, if two or more objects are instantiated from the same class, they share the same class variable.)
The boldface code in Listing 8 uses the reference variable named
ref1to access the class variable named
v1, and to cause the contents of the
Dateobject referred to by the class variable to be displayed.
|
This caused the date and time shown in Figure 3 to be displayed on my computer screen.
|
As you have probably already surmised, this is the same date and time shown earlier in Figure 1. This is because the code in Listing 8 refers to the same class variable as the code in Listing 4. Nothing has caused the contents of that class variable to change, so both Figure 1 and Figure 3 display the contents of the same
Dateobject.
(Only one class variable exists and it doesn't matter how you access it. Either way, you gain access to the same Date object whose reference is stored in the class variable. Thus, the same date and time is shown in both cases.)Another new object
If you examine the code in Listing 13 near the end of the program, you will see that an additional five-second delay is introduced at this point in the program.
Following that delay, the code in Listing 9 instantiates another new object of the class named
MyClass01, and stores the object's reference in a new reference variable named
ref2.
(The object referred to by ref1 is a different object than the object referred to by ref2 . Each object has its own instance variable named v2 , and in this case, each instance variable is initialized to instantiate and refer to a new Date object when the new MyClass01 object is instantiated.)
|
Then, the code in Listing 10 causes the contents of the
Dateobject referred to by the instance variable named
v2in the second object of the class named
MyClass01to be displayed.
|
This caused the output shown in Figure 4 to be displayed on my computer screen when I ran the program (again, you will get different results if you compile and run the program because the date and time shown is the date and time that you run the program).
|
As you have probably figured out by now, the time encapsulated in this
Dateobject is five seconds later than the time encapsulated in the
Dateobject displayed in Figure 2. This is because the program was put to sleep for five seconds between the instantiation of the two objects referred to by
ref1and
ref2.
Every object has oneEvery object instantiated from a given class has its own copy of each instance variable declared in the class definition. There is no sharing of instance variables among objects.
Each instance variable comes into existence when the object to which it belongs comes into existence, and ceases to exist when the object to which it belongs ceases to exist.
(If the instance variables are reference variables holding references to other objects, as is the case here, and if there are no other reference variables holding references to those same objects, the secondary objects cease to exist when the primary objects cease to exist. Technically, the objects may not cease to exist. Technically they become eligible for garbage collection, which means that the memory that they occupy becomes eligible for reuse. However, as a practical matter, they cease to exist insofar as the program is concerned. They are no longer accessible.)
Since the two objects referred to by
ref1and
ref2came into existence with a five-second delay, the
Dateobjects belonging to those two object reflect a five-second difference in the time encapsulated in the objects.
Only one copy of class variable existsAlso remember that if a variable is a class variable, only one copy of the variable exists, and all objects instantiated from the class share that one copy.
This is illustrated by the code in Listing 11, which uses the reference to the second object instantiated from the class named
MyClass01, to cause the contents of the class variable named
v1to be displayed.
|
The output produced by the code in Listing 11 is shown in Figure 5.
|
As you can see, this is the same as the output shown in Figure 1 and Figure 3 earlier.
Accessing the same physical class variableSince only one class variable named
v1exists, and all objects instantiated from the class named
MyClass01share that single copy, it doesn't matter whether you access the class variable using the name of the class, or access it using a reference to either of the objects instantiated from the class. In all three cases, you are accessing the same physical class variable.
Since nothing was done to cause the contents of the class variable to change after it came into existence and was initialized, Figures 1, 3, and 5 are simply three different displays of the date and time encapsulated in the same
Dateobject whose reference is stored in the class variable.
Let's revisit System.out.println...Now, I want to revisit the statement originally shown in Listing 8 and repeated in Listing 12 for viewing convenience.
|
I often tell my students that if I were out in industry, interviewing prospective Java programmers, my first question would be to ask the prospective employee to tell me everything that she knows about the statement in Listing 12.
Covers a lot of Java OOP technologyThis is not because there is a great demand for the use of this statement in real-world problems. (In fact, in a GUI-driven software product world, there is probably very little demand for the use of this statement.) Rather, it is because a lot of Java object-oriented technology is embodied in this single statement.
In that scenario, I would expect to receive a verbal dissertation of fifteen to twenty minutes in length to cover all the important points.
The short versionLet me give you the short version. There is a class named
System. The
Systemclass declares three
static(class) variables having the following types, names, and modifiers:
- public static final PrintStream out
- public static final InputStream in
- public static final PrintStream err
(Note that these class variables are also declared final , causing them to behave as constants.)Access the out variable without an object
Because
outis a class variable,
System.outreturns the contents of the class variable named
out(an object of the System class is not required in order to access a class variable of the System class).
In general, (ignoring the possibility of subclasses and interfaces) because
outis a reference variable of type
PrintStream, the returned value must either be
null(no object reference) or a reference to a valid
PrintStreamobject.
Object of the PrintStream classWhen the Java Virtual Machine starts an application running, it instantiates an object of the
PrintStreamclass and connects it to the
standard output device.
(By default, the standard output device is typically the computer screen, but it can be redirected at the operating system level to be some other device. The following discussion assumes that the screen is the standard output device.)Assign object's reference to out variable
When the
PrintStreamobject is instantiated by the virtual machine, the object's reference is assigned to the class variable of the
Systemclass named
out.
(Because the variable named out is final, the contents of the variable cannot be modified later.)Reference to a PrintStream object
Therefore, the expression
System.outreturns a reference to the
PrintStreamobject, which is connected to the standard output device.
Many instance methodsAn object of the
PrintStreamclass contains many instance methods. This includes numerous overloaded versions of a method named
println. The signature of one of those overloaded versions of the
printlnmethod follows:
public void println(Object x) Textual representation of an objectThe purpose of this overloaded version of the
printlnmethod is to:
- Create a textual representation of the object referred to by the incoming parameter of type Object (because Object is a totally generic type, this version of the println method can accept an incoming parameter that is a reference to any type of object)
- Send that textual representation to the output device
In general ... (In general, a new PrintStream object can be connected to a variety of output devices when it is instantiated. However, in the special case of the PrintStream object instantiated by the virtual machine when the program starts, whose reference is stored in the class variable named out of the System class, the purpose of the object is to provide a display path to the standard output device.)Our old friend, the toString method
To accomplish this, the code in the
printlnmethod invokes the
toStringmethod on the incoming reference.
(I discussed the toString method in detail in earlier lessons in this miniseries.)
The
toStringmethod may, or may not, have been overridden in the definition of the class from which the object was instantiated, or in some superclass of the class from which the object was instantiated.
Default version of toStringIf not overridden, the default version of the
toStringmethod defined in the
Objectclass is used to produce a textual representation of the object. As we learned in an earlier lesson, that textual representation looks something like the following:
[email protected] Overridden version of toString methodIf the class from which the object was instantiated (or some superclass of that class) contains an overridden version of the
toStringmethod, runtime polymorphism kicks in and the overridden version of the method is executed to produce the textual representation of the object.
The Date class overrides toStringIn the case of this sample program, the object was instantiated from the
Dateclass. The
Dateclass does override the
toStringmethod.
When the overridden
toStringmethod is invoked on a
Dateobject's reference, the
Stringreturned by the method looks something like that shown in Figure 6.
|
You will recall that this is the output that was produced by the code shown in Listing 8 and Listing 12.
More than you ever wanted to know ...And that is probably more than you ever wanted to know about the expression
System.out.println....
It is also probably more than you ever wanted to know about class variables, class methods, instance variables, and instance methods.
Some cautionsBefore leaving this topic, I do want to express some cautions. Basically, I want to suggest that you use static members very sparingly, if at all. Several good sets of guidelines have been published regarding the use of static members. As of this writing, you can find one of them, written by Mark L. Fussell, at the following URL.
Guidelines for use of static membersI will try to summarize the general sense of most published guidelines in a few words.
Static variablesTo begin with, don't ever use static variables without declaring them
finalunless you understand exactly why you are declaring them static.
(Static final variables, or constants, are often very appropriate. See the fields in the Color class for example.)
I can only think of a few situations where the use of a non-final static variable might be appropriate.
(One appropriate use might be to count the number of objects instantiated from a specific class. I suspect there are a few other appropriate uses as well.)Static methods
Don't declare methods static if there is any requirement for the method to remember anything from one invocation to the next.
There are many appropriate uses for static methods, but in most cases, the purpose of the method will be to completely perform some action with no requirement to remember anything from that invocation to the next.
The method should probably also be self-contained. By this I mean that all information that the method needs to do its job should either come from incoming parameters or from final static member variables (constants). The method probably should not depend on the values stored in non-final static member variables, which are subject to change over time.
(A static method only has access to other static members of the class, so it cannot depend on instance variables defined in the class.)
An appropriate example of a static method is the
sqrtmethod of the
Mathclass. This method computes and "Returns the correctly rounded positive square root of a double" where the double value is provided as a parameter to the method. Each time the method is invoked, it completes its task and doesn't attempt to save any values from that invocation to the next. Furthermore, it gets all the information that it needs to do its job from an incoming parameter.
Summary
Added complexityThe existence of static members tends to break up the simple OOP structures that I have discussed in previous lessons in this miniseries.
While static members can be useful in some situations, the existence of static members tends to complicate the overall object-oriented structure of Java.
Furthermore, the overuse of static members can lead to problems similar to those experienced in languages like C and C++ that support global variables and global functions.
The class named ClassI discussed the class named
Classand how a conceptual object of type
Classexists in memory following a reference to a specific class in the program code.
The
Classobject represents the referenced class in memory, and contains the static variables and static methods belonging to that class. (It contains some other information as well, such as the name of the superclass.)
Class members and instance membersClass variables and class methods are declared static (declaring a member static in the class definition causes to be called a class member).
Instance variables and instance methods are not declared static.
Each object has its own copy ...Every object instantiated from a given class has its own copy of each instance variable declared in the class definition. (Instance variables are not shared among objects.)
Every object instantiated from a given class acts like it has its own copy of every instance method declared in the class definition. (Although instance methods are actually shared among objects in order to reduce the amount of memory required, they are shared in such a way that they don't appear to be shared.)
Every object shares ...Every object instantiated from a given class shares the same single copy of each class variable declared in the class definition. Similarly, every object instantiated from a given class shares the same copy of each class method.
Accessing an instance memberAn instance variable or an instance method can only be accessed by using a reference to the object that owns it. Even then, it may or may not be accessible depending on the access modifier assigned by the programmer.
Accessing a class memberThe single shared copy of a class variable or a class method can be accessed in either of two ways:
- Via a reference to any object instantiated from the class
- By simply joining the name of the class to the name of the class variable or the class method
Again, the variable or method may or may not be accessible, depending on the access modifiers assigned by the programmer.
When to use class variablesIt is very often appropriate to use final static variables, as constants in your programs. It is rarely, if ever, appropriate to use non-final static variables in your programs. The use of non-final static variables should definitely be minimized.
When to use static methodsIt is often appropriate to use static methods in your programs, provided there is no requirement for the method to remember anything from one invocation to the next. Static methods should be self-contained.
What's Next?
The next lesson in this miniseries will address the special case of Array Objects.
Complete Program Listing
A complete listing of the sample program is shown in Listing 13.
|