Thinking in Java - 4th Edition
1079 pág.

Thinking in Java - 4th Edition

Disciplina:Programação Orientada a Objetos1.261 materiais32.119 seguidores
Pré-visualização50 páginas
you can see that the static initialization occurs only if it’s necessary. If you
don’t create a Table object and you never refer to Table.bowl1 or Table.bowl2, the static
Bowl bowl1 and bowl2 will never be created. They are initialized only when the first Table
object is created (or the first static access occurs). After that, the static objects are not
reinitialized.

The order of initialization is statics first, if they haven’t already been initialized by a previous
object creation, and then the non-static objects. You can see the evidence of this in the
output. To execute main( ) (a static method), the StaticInitialization class must be
loaded, and its static fields table and cupboard are then initialized, which causes those
classes to be loaded, and since they both contain static Bowl objects, Bowl is then loaded.
Thus, all the classes in this particular program get loaded before main( ) starts. This is
usually not the case, because in typical programs you won’t have everything linked together
by statics as you do in this example.

To summarize the process of creating an object, consider a class called Dog:

1. Even though it doesn’t explicitly use the static keyword, the constructor is actually a
static method. So the first time an object of type Dog is created, or the first time a
static method or static field of class Dog is accessed, the Java interpreter must
locate Dog.class, which it does by searching through the classpath.

2. As Dog.class is loaded (creating a Class object, which you’ll learn about later), all of
its static initializers are run. Thus, static initialization takes place only once, as the
Class object is loaded for the first time.

3. When you create a new Dog( ), the construction process for a Dog object first

allocates enough storage for a Dog object on the heap.

4. This storage is wiped to zero, automatically setting all the primitives in that Dog
object to their default values (zero for numbers and the equivalent for boolean and
char) and the references to null.

5. Any initializations that occur at the point of field definition are executed.

6. Constructors are executed. As you shall see in the Reusing Classes chapter, this might

actually involve a fair amount of activity, especially when inheritance is involved.

Explicit static initialization

Java allows you to group other static initializations inside a special “static clause”
(sometimes called a static block) in a class. It looks like this:

130 Thinking in Java Bruce Eckel

//: initialization/Spoon.java
public class Spoon {
 static int i;
 static {
 i = 47;
 }
} ///:~

It appears to be a method, but it’s just the static keyword followed by a block of code. This
code, like other static initializations, is executed only once: the first time you make an object
of that class or the first time you access a static member of that class (even if you never
make an object of that class). For example:

//: initialization/ExplicitStatic.java
// Explicit static initialization with the "static" clause.
import static net.mindview.util.Print.*;
class Cup {
 Cup(int marker) {
 print("Cup(" + marker + ")");
 }
 void f(int marker) {
 print("f(" + marker + ")");
 }
}
class Cups {
 static Cup cup1;
 static Cup cup2;
 static {
 cup1 = new Cup(1);
 cup2 = new Cup(2);
 }
 Cups() {
 print("Cups()");
 }
}
public class ExplicitStatic {
 public static void main(String[] args) {
 print("Inside main()");
 Cups.cup1.f(99); // (1)
 }
 // static Cups cups1 = new Cups(); // (2)
 // static Cups cups2 = new Cups(); // (2)
} /* Output:
Inside main()
Cup(1)
Cup(2)
f(99)
*///:~

The static initializers for Cups run when either the access of the static object cup1 occurs
on the line marked (1), or if line (1) is commented out and the lines marked (2) are
uncommented. If both (1) and (2) are commented out, the static initialization for Cups
never occurs, as you can see from the output. Also, it doesn’t matter if one or both of the lines
marked (2) are uncommented; the static initialization only occurs once.

Exercise 13: (1) Verify the statements in the previous paragraph.

Initialization & Cleanup 131 

Exercise 14: (1) Create a class with a static String field that is initialized at the point of
definition, and another one that is initialized by the static block. Add a static method that
prints both fields and demonstrates that they are both initialized before they are used.

Non-static instance initialization

Java provides a similar syntax, called instance initialization, for initializing non-static
variables for each object. Here’s an example:

//: initialization/Mugs.java
// Java "Instance Initialization."
import static net.mindview.util.Print.*;
class Mug {
 Mug(int marker) {
 print("Mug(" + marker + ")");
 }
 void f(int marker) {
 print("f(" + marker + ")");
 }
}
public class Mugs {
 Mug mug1;
 Mug mug2;
 {
 mug1 = new Mug(1);
 mug2 = new Mug(2);
 print("mug1 & mug2 initialized");
 }
 Mugs() {
 print("Mugs()");
 }
 Mugs(int i) {
 print("Mugs(int)");
 }
 public static void main(String[] args) {
 print("Inside main()");
 new Mugs();
 print("new Mugs() completed");
 new Mugs(1);
 print("new Mugs(1) completed");
 }
} /* Output:
Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
*///:~

You can see that the instance initialization clause:

{

132 Thinking in Java Bruce Eckel

 mug1 = new Mug(1);
 mug2 = new Mug(2);
 print("mug1 & mug2 initialized");
}

looks exactly like the static initialization clause except for the missing static keyword. This
syntax is necessary to support the initialization of anonymous inner classes (see the Inner
Classes chapter), but it also allows you to guarantee that certain operations occur regardless
of which explicit constructor is called. From the output, you can see that the instance
initialization clause is executed before either one of the constructors.

Exercise 15: (1) Create a class with a String that is initialized using instance
initialization.

Array initialization
An array is simply a sequence of either objects or primitives that are all the same type and are
packaged together under one identifier name. Arrays are defined and used with the square-
brackets indexing operator [ ]. To define an array reference, you simply follow your type
name with empty square brackets:

int[] a1;

You can also put the square brackets after the identifier to produce exactly the same
meaning:

int a1[];

This conforms to expectations from C and C++ programmers. The former style, however, is
probably a more sensible syntax, since it says that the type is “an int array.” That style will be
used in this book.

The compiler doesn’t allow you to tell it how big the array is. This brings us back to that issue
of “references.” All that you have at this point is a reference to an array (you’ve allocated
enough storage for that reference), and there’s been no space allocated for the array object
itself. To create storage for the array, you must write an initialization expression. For arrays,
initialization can appear anywhere in your code, but you can also use a special kind of
initialization expression that must occur at the point where the array is created. This special
initialization is a set of values surrounded by curly braces. The storage allocation (the
equivalent of using new) is taken care of by the compiler in this case. For example:

int[] a1 = { 1, 2, 3, 4, 5 };

So why would you ever define an array reference without an array?

int[] a2;

Well, it’s possible to assign one array to another in Java, so you can say:

a2 = a1;

What you’re really doing is copying a reference, as demonstrated