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

Thinking in Java - 4th Edition


DisciplinaProgramação Orientada A Objetos4.468 materiais62.667 seguidores
Pré-visualização50 páginas
you can see that the static initialization occurs only if it\u2019s necessary. If you 
don\u2019t 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\u2019t 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\u2019t 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\u2019t 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\u2019ll 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 \u201cstatic clause\u201d 
(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\u2019s 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\u2019t 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\u2019s 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 \u201can int array.\u201d That style will be 
used in this book. 
The compiler doesn\u2019t allow you to tell it how big the array is. This brings us back to that issue 
of \u201creferences.\u201d All that you have at this point is a reference to an array (you\u2019ve allocated 
enough storage for that reference), and there\u2019s 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\u2019s possible to assign one array to another in Java, so you can say: 
a2 = a1; 
What you\u2019re really doing is copying a reference, as demonstrated