5.4 Class DeclarationsA class declaration creates a reference type in Java. The class declaration also specifies the implementation of the class, including its variables, constructors, and methods. The formal definition of a class declaration is:
While the above diagram may seem complicated, a class declaration is really made up of six distinct things:
References Classes; ClassOrInterfaceName 4.1.6; Class Members; Identifiers Class ModifiersThe keywords public, abstract, and final can appear as modifiers at the beginning of a class declaration. In this situation, these modifiers have the following meanings:[3]
References Compilation Units; Inner class modifiers; Local class modifiers; Method modifiers; Variable modifiers Class NameThe identifier that follows the keyword class is the name of the class. This identifier can be used as a reference type wherever the class is accessible. References Class Types Class InheritanceThe extends clause specifies the superclass of the class being declared. If a class is declared without an extends clause, the class Object is its implicit superclass. The class inherits all of the accessible methods and variables of its superclass. If a class is declared final, it cannot appear in an extends clause for any other class. The implements clause specifies any interfaces implemented by the class being declared. Unless it is an abstract class, the class (or one of its superclasses) must define implementations for all of the methods declared in the interfaces. References Inheritance; Interfaces; Interface Declarations; Object Class MembersFields are the variables, methods, constructors, static (load-time) initializers, instance initializers, nested top-level classes and interfaces, and member classes that are declared as part of a class:
A member declaration causes the member to be defined throughout the entire class and all of its subclasses. This means that it is not a problem to have forward references to members, or in other words, you can use members in a class before you have defined them. For example:
class foo { void doIt() { countIt(); } void countIt() { i++; } int i; } References Constructors; Nested Top-Level and Member Classes; Nested Top-Level Interfaces; Instance Initializers; Methods; Static Initializers; Variables VariablesA variable that is declared as a member in a class is called a field variable. A field variable is different from a local variable, which is declared within a method or a block. The formal definition of a variable declaration is:
While the above diagram may seem complicated, a variable declaration is really made up of four distinct things:
Here are some examples of variable declarations:
int x; public static final double[] k, m[]; References Variable initializers; Expression 4; Identifiers; Local Variables; Type 3 Variable modifiersThe modifiers public, protected, and private can be used in the declaration of a field variable to specify the accessibility of the variable. In this situation, the modifiers have the following meanings:[4]
If a field variable is not declared with any of the access modifiers, the variable has the default accessibility. Default access is often called "friendly" access because it is similar to friendly access in C++. A variable with default access is accessible in any class that is part of the same package as the class in which the variable is declared. However, a friendly variable is not accessible to classes outside of the package in which it is declared, even if the desired classes are subclasses of the class in which it is declared. The keywords static, final, transient, and volatile can also be used in the declaration of a field variable. These modifiers have the following meanings:
References Class Modifiers; Inner class modifiers; Local class modifiers; Method modifiers Variable typeA field variable declaration must always specify the type of the variable. If the declaration of a field variable uses a primitive type, the variable contains a value of the specified primitive type. If the declaration uses a reference type, the variable contains a reference to the specified type of object. The presence of square brackets in a variable declaration, after either the type or variable name, indicates that the variable contains a reference to an array. For example:
int a[]; // a is an array of int int[] b; // b is also an array of int It is also possible to declare a variable to contain an array of arrays, or more generally, arrays nested to any level. Each pair of square brackets in the declaration corresponds to a dimension of the array; it makes no difference whether the brackets appear after the type or the variable name. For example:
int[][][] d3; // Each of these is an array of int[][] f3[]; // arrays of arrays of integers int[] g3[][]; int h3[][][]; int[] j3, k3[]; // An array and an array of arrays References Array Types; Primitive Types; Reference Types Variable nameThe identifier that follows the variable type is the name of the variable. This identifier can be used anywhere that the variable is accessible. It is an error to declare two field variables with the same name in the same class. It is also an error to declare a field variable with the same name as a method declared in the same class or any of its superclasses. If a field variable is declared with the same name as a variable declared in a superclass, the variable in the superclass is considered to be shadowed. If a variable is shadowed in a class, it cannot be accessed as a field of that class. However, a shadowed variable can be accessed by casting a reference to an object of that class to a reference to the appropriate superclass in which the variable is not shadowed. For example:
class A { int x = 4; } class B extends A { int x = 7; B () { int i = x; // i gets the value of B's x int h = ((A)this).x; // h gets the value of A's x } } Alternatively, if a variable is shadowed in a class but not in its immediate superclass, the methods of the class can access the shadowed variable using the keyword super. In the above example, this would look as follows:
int h = super.x; // h gets the value of A's x If a method is declared with the same name and parameters as a method in a superclass, the method in the superclass is considered to be overridden. Note that variable shadowing is different than method overriding. The most important difference is that using a reference to an instance of an object's superclass does not provide access to overridden methods. Overriding is described in detail in Method name. References Field Expressions; Identifiers; Inheritance; Method name Variable initializersA variable declaration can contain an initializer. However, if a variable is declared to be final, it must either have an initializer or be initialized exactly once in a static initializer, instance initializer, or constructor. If the variable is of a non-array type, the expression in the initializer is evaluated and the variable is set to the result of the expression, as long as the result is assignment-compatible with the variable. If the variable is of an array type, the initializer must be an array initializer:
Each expression or array initializer in an array initializer is evaluated and becomes an element of the array produced by the initializer. The variable is set to the array produced by the initializer, as long as the assignment is assignment-compatible. Here are some examples of actual array initializers:
short a[] = {2,5,8,2,11}; // array of 5 shorts int s[][] = { {3,45,8}, // array of 4 arrays {12,9,33}, // of 3 ints {7,22,53}, {33,1,2} }; Note that a trailing comma is allowed within an array initializer. For example, the following is legal:
int x[] = {2,23,4,}; Any initializers for class variables (i.e., static variables) are evaluated when the class is loaded. The initializer for a class variable cannot refer to any instance variables in the class. An initializer for a static variable cannot refer to any static variables that are declared after its own declaration. The initial value of a class variable can also be set in a static initializer for the class; static initializers are described in Static Initializers. Any initializers for instance variables are evaluated when a constructor for the class is called to create an instance of the class. Every class has at least one constructor that explicitly or implicitly calls one of the constructors of its immediate superclass before it does anything else. When the superclass's constructor returns, any instance variable initializers (and instance initializers) are evaluated before the constructor does anything else. The initial value of an instance variable can also be set in an instance initializer; instance initializers are described in Instance Initializers. Of course, it is also possible to set the initial values of instance variables explicitly in a constructor. Constructors are described in Constructors. If a variable declaration does not contain an initializer, the variable is set to a default value. The actual value is determined by the variable's type. Table 5-1 shows the default values used for the various types in Java.
For an array, every element of the array is set to the appropriate default value, based on the type of elements in the array. Here are some examples of variable declarations, with and without initializers:
int i,j; // initialized to zero long k = 243L; double d = k*1.414; String s; // initialized to null char c[] = new char[123]; float f[] = { 3.2f, 4.7f, 9.12f, 345.9f}; Double dbl = new Double(382.3748); java.io.File fl = new File("/dev/null"); Object o = fl; References Array Types; Assignment Operators; Constructors; Expression 4; Instance Initializers; Static Initializers; Variable modifiers MethodsA method is a piece of executable code that can be called as a subroutine or a function. A method can be passed parameters by its caller; the method can also return a result to its caller. In Java, a method can only be declared as a field in a class. The formal definition of a method declaration is:
While the above diagram may seem complicated, a method declaration is really made up of six distinct things:
Here are some examples of method declarations:
public static void main(String[] argv) { System.out.println( argv[0] ); } int readSquare(DataInputStream d) throws IOException { int i = d.readInt(); return i*i; } int filledArray(int length, int value) [] { int [] array = new int [length]; for (int i = 0; i < length; i++ ) { array[i] = value; } return array; } Unlike C/C++, Java only allows method declarations that fully specify the type and number of parameters that the method can be called with. References Blocks; ClassOrInterfaceName 4.1.6; Exception Handling 9; Method formal parameters; Identifiers; Type 3 Method modifiersThe modifiers public, protected, and private can be used in the declaration of a method to specify the accessibility of the method. In this situation, the modifiers have the following meanings:
If a method is not declared with any of the access modifiers, it has the default accessibility. Default access is often called "friendly" access because it is similar to friendly access in C++. A method with default access is accessible in any class that is part of the same package as the class in which the method is declared. However, a friendly method is not accessible to classes outside of the package in which it is declared, even if the classes are subclasses of the class in which it is declared. The keywords static, final, abstract, native, and synchronized can also be used in the declaration of a method. These modifiers have the following meanings:
References Class Modifiers; Inner class modifiers; Local class modifiers; Variable modifiers Method return typeA method declaration must always specify the type of value returned by the method. The return value can be of a primitive type or of a reference type. If the method does not return a value, it should be declared with its return type specified as void. The return type comes before the name of the method in the method declaration. The presence of square brackets in a method declaration, after either the return type or the formal parameters, indicates that the method returns a reference to the specified type of array. For example:
int a()[] {...}; // a returns an array of int int[] b() {...}; // b also returns an array of int It is also possible to declare that a method returns a reference to an array of arrays, or more generally, arrays nested to any level. Each pair of square brackets in the declaration corresponds to a dimension of the array; it makes no difference whether the brackets appear after the return type or the formal parameters. For example:
int[][][] d3() {...}; // Each of these returns an array of int[][] f3()[] {...}; // arrays of arrays of integers int[] g3()[][] {...}; int h3()[][][] {...}; If a method is declared with the void return type, any return statement that appears within the method must not contain a return value. Because a method with a void return type does not return a value, such a method can only be called from an expression statement that consists of a method call expression. On the other hand, if a method is declared with a return type other than void, it must return through an explicit return statement that contains a return value that is assignment-compatible with the return type of the method. References Array Types; Expression Statements; Primitive Types; Reference Types; The return Statement Method nameThe identifier that follows the return type is the name of the method. This identifier can be used anywhere that the method is accessible. It is an error to declare two methods that have the same name, the same number of parameters, and the same type for each corresponding parameter in the same class. It is also an error to declare a method with the same name as a variable declared in the same class or any of its superclasses. A method is said to be overloaded if there is more than one accessible method in a class with the same name, but with parameters that differ in number or type.[5] This situation can arise if two or more such methods are declared in the same class. It can also occur when at least one of the methods is defined in a superclass and the rest are in a subclass.
Overloaded methods aren't required to have the same return type. For example:
int max(int x, int y){return x>y ? x : y;} double max(double x, double y){return x>y ? x : y;} A method that is inherited from a superclass is said to be overridden if a method in the inheriting class has the same name, number of parameters, and types of parameters as the inherited method. If the overridden method returns void, the overriding method must also return void. Otherwise, the return type of the overriding method must be the same as the type of the overridden method. An overriding method can be more accessible than the overridden method, but it cannot be less accessible. In other words, a subclass cannot hide things that are visible in its superclass, but it can make visible things that are hidden. An object is considered to be an instance of its own class, as well as an instance of each of its superclasses. As a result, you can use an object reference to call a method in an object and not worry about whether the object is actually an instance of a subclass of the type of the reference. If a subclass were allowed to override methods of its superclass with methods that were less accessible, you would no longer be able to use a reference without regard to the actual type of the object being referenced. For example, Object is the superclass of String. This means that a variable declared to contain a reference to an Object may actually refer to a String. The Object class defines a public method called hashCode(), so a reference to the Object class can be used to call the hashCode() method of whatever subclass of Object it refers to. Allowing a subclass of Object to declare a private hashcode() method would be inconsistent with this usage. Table 5-2 shows the access modifiers that are permitted for an overriding method, based on the access allowed for the overridden method.
If a method in the superclass is declared private, it is not inherited by the subclass. This means that a method in the subclass that has the same name, number of parameters, and types of parameters does not override the private method in the superclass. As a result, the method in the subclass can have any return type and there are no restrictions on its accessibility. Non-static methods must be called through an object reference. If a non-static method is called with no explicit object reference, it is implicitly called using the object reference this. At compile-time, the type of the object reference is used to determine the combinations of method names and parameters that are accessible to the calling expression (see Method Call Expression). At runtime, however, the actual type of the object determines which of the methods is called. If the actual object is an instance of a subclass of the referenced class and the subclass overrides the method being called, the overriding method in the subclass is invoked. In other words, the actual type of the object is used to determine which method to call, not the type of the reference to that object. This means that you cannot simply cast an object reference to a superclass of the class of the actual object to call to an overridden method. Instead, you use the keyword super to access an overridden method in the superclass. For example:
class A { void doit() { ... } } class B extends A { void doit() { super.doit(); // calls overridden A.doit() } public static void main(String argv[]) { B b = new B(); ((A)b).doit(); // calls B.doit() } } The doit() method in class B calls the overridden doit() method in class A using the super construct. But, in main(), the doit() method in class B is invoked because casting a reference does not provide access to overridden methods. References Identifiers; Inheritance; Method Call Expression; Variable name Method formal parametersThe formal parameters in a method declaration specify a list of variables to which values are assigned when the method is called:
Within the block that contains the implementation of the method, the method's formal parameters are treated as local variables; the name of each formal parameter is available as an identifier in the method's implementation. Formal parameters differ from local variables only in that their declaration and value come from outside the method's block. If a formal parameter is declared final, any assignment to that parameter generates an error. The syntax for declaring final parameters is not supported prior to Java 1.1. If a method has no formal parameters, the parentheses must still appear in the method declaration. Here's an example of a method declaration with formal parameters:
abstract int foo(DataInputStream d, Double[] values, int weights[]) ; The presence of square brackets in a formal parameter declaration, either as part of a reference type or after the name of a formal parameter, indicates that the formal parameter is an array type. For example:
foo(int a[], // a is an array of int int[] b) // b is also an array of int It is also possible to declare that a formal parameter is an array of arrays, or more generally, arrays nested to any level. Each pair of square brackets in the declaration corresponds to a dimension of the array; it makes no difference whether the brackets appear with the type or after the name of the formal parameter. For example:
int[][][] d3 // Each of these is an array of int[][] f3[] // arrays of arrays of integers int[] g3[][] int h3[][][] References Array Types; Blocks; Identifiers; Local Variables; Type 3 Method throws clauseIf a method is expected to throw any exceptions, the method declaration must declare that fact in a throws clause. Java requires that most types of exceptions either be caught or declared, so bugs caused by programmers forgetting to handle particular types of exceptions are uncommon in Java programs. If a method implementation contains a throw statement, or if the method calls another method declared with a throws clause, there is the possibility that an exception will be thrown from within the method. If the exception is not caught, it will be thrown out of the method to its caller. Any exception that can be thrown out of a method in this way must be listed in a throws clause in the method declaration, unless the exception is an instance of Error, RuntimeException, or a subclass of one of those classes. Subclasses of the Error class correspond to situations that are not easily predicted, such as the system running out of memory. Subclasses of RuntimeException correspond to many common runtime problems, such as illegal casts and array index problems. The classes listed in a throws clause must be Throwable or any of its subclasses; the Throwable class is the superclass of all objects that can be thrown in Java. Consider the following example:
import java.io.IOException; class throwsExample { char[] a; int position; ... // Method explicitly throws an exception int read() throws IOException { if (position >= a.length) throw new IOException(); return a[position++]; } // Method implicitly throws an exception String readUpTo(char terminator) throws IOException { StringBuffer s = new StringBuffer(); while (true) { int c = read(); // Can throw IOException if (c == -1 || c == terminator) { return s.toString(); } s.append((char)c); } return s.toString(): } // Method catches an exception internally int getLength() { String s; try { s = readUpTo(':'); } catch (IOException e) { return 0; } return s.length(); } // Method can throw a RuntimeException int getAvgLength() { int count = 0; int total = 0; int len; while (true){ len = getLength(); if (len == 0) break; count++; total += len; } return total/count; // Can throw ArithmeticException } } The method read() can throw an IOException, so it declares that fact in its throws clause. Without that throws clause, the compiler would complain that the method must either declare IOException in its throws clause or catch it. Although the readUpTo() method does not explicitly throw any exceptions, it calls the read() method that does throw an IOException, so it declares that fact in its throws clause. Whether explicitly or implicitly thrown, the requirement to catch or declare an exception is the same. The getLength() method catches the IOException thrown by readUpTo(), so it does not have to declare the exception. The final method, getAvgLength(), can throw an ArithmeticException if count is zero. Because ArithmeticException is a subclass of RuntimeException, the fact that it can be thrown out of getAvgLength() does not need to be declared. If a method overrides another method, the overriding method cannot throw anything that the overridden method does not throw. Specifically, if the declaration of a method contains a throws clause, any method that overrides that method cannot include any classes in its throws clause that are not declared in the overridden method. This restriction avoids surprises. When a method is called, the Java compiler requires that all of the objects listed the method's throws clause are either caught by the calling method or declared in the calling method's throws clause. The requirement that an overriding method cannot include any class in its throws clause that is not in the overridden method's throws clause ensures that the guarantee made by the compiler is respected by the runtime environment. References Exception Handling 9; The throw Statement; The try Statement Method implementationA method declaration must end with either a block or a semicolon. If either the abstract or native modifier is used in the declaration, the declaration must end with a semicolon. All other method declarations must end with a block that defines the implementation of the method. References Blocks; Method modifiers ConstructorsA constructor is a special kind of method that is designed to set the initial values of an object's instance variables and do anything else that is necessary to create an object. Constructors are only called as part of the object creation process. The declaration of a constructor does not include a return type. The name of a constructor is always the same as the name of the class:
A constructor declaration is really made up of five distinct things:
Here is an example that shows a class with some constructors:
class Construct { private Construct(Double[] values, int weights[]) { } public Construct(OutputStream o, Double[] values, int weights[]) throws IOException { this(values, weights); o.write(weights[0]); } public Construct() { } } References Blocks; ClassOrInterfaceName 4.1.6; Exception Handling 9; Method formal parameters; Identifiers; Object Creation Constructor modifiersThe modifiers public, protected, and private can be used in the declaration of a constructor to specify the accessibility of the constructor. In this situation, the modifiers have the following meanings:
If a constructor is not declared with any of the access modifiers, the constructor has the default accessibility. Default access is often called "friendly" access because it is similar to friendly access in C++. A constructor with default access is accessible in any class that is part of the same package as the class in which the constructor is declared. However, a friendly constructor is not accessible in subclasses of the class in which it is declared. References Class Modifiers; Inner class modifiers; Local class modifiers Constructor nameA constructor has no name of its own. The identifier that appears in a constructor declaration must be the same as the name of the class in which the constructor is declared. This identifier can be used anywhere that the constructor is accessible. References Class Types Constructor return typeA constructor has no declared return type; it always returns an object that is an instance of its class. A return statement in a constructor is treated the same as it is in a method declared to return void; the return statement must not contain a return value. Note that it is not possible to explicitly declare a constructor to have the return type void. References The return Statement Constructor formal parametersThe formal parameters in a constructor declaration specify a list of variables to which values are assigned when the constructor is called. Within the block that contains the implementation of the constructor, the constructor's formal parameters are treated as local variables; the name of each formal parameter is available as an identifier in the constructor's implementation. Formal parameters differ from local variables only in that their declaration and value come from outside the constructor's block. If a formal parameter is declared final, any assignment to that parameter generates an error. The syntax for declaring final parameters is not supported prior to Java 1.1. If a constructor has no formal parameters, the parentheses must still appear in the constructor declaration. The presence of square brackets in a formal parameter declaration, either as part of a reference type or after the name of a formal parameter, indicates that the formal parameter is an array type. For example:
Foo(int a[], // a is an array of int int[] b) // b is also an array of int It is also possible to declare that a formal parameter is an array of arrays, or more generally, arrays nested to any level. Each pair of square brackets in the declaration corresponds to a dimension of the array; it makes no difference whether the brackets appear with the type or after the name of the formal parameter. For example:
int[][][] d3 // Each of these is an array of int[][] f3[] // arrays of arrays of integers int[] g3[][] int h3[][][] References Array Types; Blocks; Method formal parameters; Local Variables Constructor throws clauseIf a constructor is expected to throw any exceptions, the constructor declaration must declare that fact in a throws clause. If a constructor implementation contains a throw statement, or if the constructor calls another constructor or method declared with a throws clause, there is the possibility that an exception will be thrown from within the constructor. If the exception is not caught, it will be thrown out of the constructor to its caller. Any exception that can be thrown out of a constructor in this way must be listed in a throws clause in the constructor declaration, unless the exception is an instance of Error, RuntimeException, or a subclass of one of those classes. Subclasses of the Error class correspond to situations that are not easily predicted, such as the system running out of memory. Subclasses of RuntimeException correspond to many common runtime problems, such as illegal casts and array index problems. The classes listed in a throws clause must be Throwable or any of its subclasses; the Throwable class is the superclass of all objects that can be thrown in Java. References Exception Handling 9; The throw Statement; The try Statement Constructor implementationThe block at the end of a constructor declaration contains the implementation of the constructor. The block is called the constructor body. The first statement in a constructor body is special; it is the only place that Java allows an explicit call to a constructor outside of an allocation expression. An explicit call to a constructor has a special form:
In an explicit constructor call, the keyword this can be used to specify a call to a constructor in the same class. The keyword super can be used to specify a call to a constructor in the immediate superclass. For example:
class Square extends RegularPolygon { // Construct a square without specifying the length of the sides Square() { this(5); } // Construct a square with sides of a specified length Square(int len) { super(4,len); } } The first constructor simply calls the second constructor with the argument 5. The second constructor calls a constructor in the immediate superclass to create a four-sided regular polygon with sides of the given length. Except for the constructors in the class Object, a constructor always begins by calling another constructor in the same class or in its immediate superclass. If the first statement in a constructor is not an explicit call to another constructor using this or super and the class is not Object, the compiler inserts a call to super() before the first statement in the constructor. In other words, if a constructor does not begin with an explicit call to another constructor, it begins with an implicit call to the constructor of its immediate superclass that takes no argument. The result is constructor chaining: a constructor for each superclass of a class is called before the constructor of the class executes any of its own code. After all of the calls to the superclasses' constructors (explicit or implicit) have returned, any instance variables that have initializers are initialized, and finally the constructor executes its own code. Constructor chaining places a restriction on the arguments that can be passed to a constructor in an explicit constructor call. The expressions provided as arguments must not refer to any instance variables of the object being created because these instance variables are not initialized until the superclass's constructor returns. References ArgumentList 4.1.8; Object Allocation Expressions; this; super The default constructorIf a class declaration does not contain any constructor declarations, Java supplies a default constructor for the class. The default constructor is public, it takes no arguments, and it simply calls the constructor of its class's superclass that takes no arguments. The default constructor is approximately equivalent to:
public MyClass() { super(); } Because Java creates a default constructor only for a class that does not have any explicitly declared constructors, it is possible for the superclass of that class not to have a constructor that takes no arguments. If a class declaration does not contain a constructor declaration and its immediate superclass does not have a constructor that takes no arguments, the compiler issues an error message because the default constructor references a non-existent constructor in the superclass. The default constructor for the class Object does not contain a call to another constructor because class Object has no superclass. References Object Constructor inheritanceA subclass does not inherit constructors from its superclass, as it does normal methods. This is one important difference between regular methods and constructors: constructors are not inherited. However, a subclass can access a constructor in its superclass, as long as the constructor is accessible, based on any access modifiers used in its declaration. This example illustrates the difference between inheritance and accessibility:
public class A { public A (int q) { } } public class B extends A { public B () { super(5); } } Although class B is a subclass of class A, B does not inherit the public constructor in A that takes a single argument. This means that if you try to create a new instance of B using an allocation expression with a single argument, you'll get an error message from the compiler. Here's an erroneous call:
B b1 = new B(9); However, as shown in the example, the constructor in B can access the constructor in A using the keyword super. The finalize methodA class declaration can include a special method that is called before an instance of the class is destroyed by the garbage collector. This method is called a finalizer ; it has the name finalize(). The finalize() method for a class must be declared with no parameters, a void return type, and no modifiers:
void finalize() {...} If a class has a finalize() method, it is normally called by the garbage collector before an object of that class type is destroyed. A program can also explicitly call an object's finalize() method, but in this case, the garbage collector does not call the method during the object destruction process. If the garbage collector does call an object's finalize() method, the garbage collector does not immediately destroy the object because the finalize() method might do something that results in a reference to the object. Thus the garbage collector waits to destroy the object until it can again prove it is safe to do so. The next time the garbage collector decides it is safe to destroy the object, it does so without calling the finalizer again. In any case, a finalize() method is never called more than once by the garbage collector for a particular object. A superclass of the class may also define a finalize() method, but Java does not provide a mechanism that automatically calls the superclass's finalize() method. If a class contains a finalize() method, it is a good idea for that method to call super.finalize() as the very last thing that it does. This technique ensures that the finalize() method of the superclass gets called. The technique even works if the superclass does not explicitly define a finalize() method, since every class inherits a default finalize() method from the Object class. This default finalize method does not do anything. References Object Destruction Static InitializersA static initializer is a piece of code that is executed when a class is loaded. A static initializer is simply a block of code in a class declaration that is preceded by the keyword static:
A class is loaded when its definition is needed by another class. You can specifically request that a class be loaded by calling the forName() method of the Class class on the class you want to load. Alternatively, you can use the loadClass() method of a ClassLoader object to load a class directly. When a class is loaded, a Class object is created to represent it and storage for the class's static variables is allocated. When a class is initialized, its static initializers and static variable initializers are evaluated in the order in which they appear in the class declaration. For example, here is a class that contains both static initializers and static variable initializers:
class foo { static int i = 4; static { i += 2; j = 5 * i; } static int j = 7; static double d; static frame f = new Frame(); static { d = Math.tan(Math.PI/j); } } When the foo class is loaded, here is what happens. First, the variable i is set to 4. Then the first static initializer is executed. It increments i by 2, which makes it 6, and sets j to 5*i, which is 30. Next, the variable j is set to 7 by its initializer; this overwrites the value that was set in the static initializer. The variable f is then set to the new Frame object created by its initializer. Finally, the second static initializer is executed. It sets the variable d to , which is . Notice that the first static initializer uses the variable j, even though the variable is not declared until after the static initializer. A static initializer can refer to a static variable that is declared after the static initializer. However, the same is not true for static variable initializers. A static variable initializer cannot refer to any variables that are declared after its own declaration, or the compiler generates an error message. The following class declaration is erroneous:
class foo { static int x = y*3; // error because y defined after x static int y; } If an exception is thrown out of a static initializer, the method that caused the class to be defined throws an ExceptionInInitializerError. This ExceptionInInitializerError contains a reference to the original exception that can be fetched by calling its getException() method. Instance InitializersAn instance initializer is a piece of code that is executed when an instance of a class is created. Specifically, it is executed after the object's immediate superclass constructor returns, but before the constructor of the class itself runs. An instance initializer is simply a block of code in a class that is not in any method. Here is the formal syntax:
Every class has at least one constructor that explicitly or implicitly calls one of the constructors of its immediate superclass before it does anything else. When the superclass's constructor returns, any instance initializers and instance variable initializers are evaluated before the constructor does anything else. The instance initializers and instance variable initializers are evaluated in the order in which they appear in the class declaration. If an instance initializer throws an exception, the exception appears to have come from the constructor that called the superclass's constructor. References Blocks; Constructors; Variable initializers Nested Top-Level and Member ClassesNested top-level classes and member classes are classes that are declared inside of another class. Just as with a top-level class declaration, the declaration of a nested top-level class or member class creates a reference type in Java. Here's the formal definition of a nested top-level or member class declaration:
A class declared inside of another class has access to all of the variables, methods, and other inner classes of the enclosing class. If a nested top-level or member class is not private, it can also be accessed outside of its enclosing class by qualifying its name with the name of its enclosing class, as follows:
EnclosingClass.InnerClass The syntax for declaring nested top-level classes and member classes is not supported prior to Java 1.1. References Nested top-level classes and interfaces; Member classes; Class Declarations Inner class modifiersThe keywords public, protected, and private can be used in the declaration of a nested top-level or member class to specify the accessibility of the inner class. In this situation, the modifiers have the following meanings:
If a nested top-level or member class is not declared with any of the access modifiers, the class has the default accessability. Default access is often called "friendly" access because it is similar to friendly access in C++. An inner class with default access is accessible in any class that is part of the same package as the enclosing class. However, a friendly inner class is not accessible to classes outside of the package of the enclosing class, even if the desired classes are subclasses of the enclosing class. The keywords abstract, final, and static can also be used in the declaration of a nested top-level or member class. These modifiers have the following meanings:
References Class Modifiers; Local class modifiers Inner class membersThe body of a nested top-level or member class cannot declare any static variables, static methods, static classes, or static initializers. Beyond those restrictions, the remainder of the declaration is the same as that for a top-level class declaration, which is described in Class Declarations. References Class Declarations; Constructors; Instance Initializers; Methods; Nested Top-Level and Member Classes; Static Initializers; Variables | |||||||||||||||||||||||||||||||||||||||||||||||
|