And initializes object java

Initializing Fields

As you have seen, you can often provide an initial value for a field in its declaration:

public class BedAndBreakfast < // initialize to 10 public static int capacity = 10; // initialize to false private boolean full = false; >

This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.

Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.

Читайте также:  Java check running threads

Static Initialization Blocks

A static initialization block is a normal block of code enclosed in braces, < >, and preceded by the static keyword. Here is an example:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

There is an alternative to static blocks — you can write a private static method:

The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.

Initializing Instance Members

Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.

Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

A final method cannot be overridden in a subclass. This is discussed in the lesson on interfaces and inheritance. Here is an example of using a final method for initializing an instance variable:

This is especially useful if subclasses might want to reuse the initialization method. The method is final because calling non-final methods during instance initialization can cause problems.

Previous page: Understanding Class Members
Next page: Summary of Creating and Using Classes and Objects

Источник

Class and object initialization in Java

Java 101: Class and object initialization

Classes and objects in Java must be initialized before they are used. You’ve previously learned that class fields are initialized to default values when classes are loaded and that objects are initialized via constructors, but there is more to initialization. This article introduces all of Java’s features for initializing classes and objects.

Download the source code for example applications in this tutorial. Created by Jeff Friesen for JavaWorld.

How to initialize a Java class

Before we explore Java’s support for class initialization, let’s recap the steps of initializing a Java class. Consider Listing 1.

Listing 1. Initializing class fields to default values

Listing 1 declares class SomeClass . This class declares nine fields of types boolean , byte , char , double , float , int , long , short , and String . When SomeClass is loaded, each field’s bits are set to zero, which you interpret as follows:

false 0 \u0000 0.0 0.0 0 0 0 null

The previous class fields were implicitly initialized to zero. However, you can also explicitly initialize class fields by directly assigning values to them, as shown in Listing 2.

Listing 2. Initializing class fields to explicit values

Each assignment’s value must be type-compatible with the class field’s type. Each variable stores the value directly, with the exception of st . Variable st stores a reference to a String object that contains abc .

Referencing class fields

When initializing a class field, it’s legal to initialize it to the value of a previously initialized class field. For example, Listing 3 initializes y to x ‘s value. Both fields are initialized to 2 .

Listing 3. Referencing a previously declared field

However, the reverse is not legal: you cannot initialize a class field to the value of a subsequently declared class field. The Java compiler outputs illegal forward reference when it encounters this scenario. Consider Listing 4.

Listing 4. Attempting to reference a subsequently declared field

The compiler will report illegal forward reference when it encounters static int x = y; . This is because source code is compiled from the top down, and the compiler hasn’t yet seen y . (It would also output this message if y wasn’t explicitly initialized.)

Class initialization blocks

In some cases you may want to perform complex class-based initializations. You will do this after a class has been loaded and before any objects are created from that class (assuming that the class isn’t a utility class). You can use a class initialization block for this task.

A class initialization block is a block of statements preceded by the static keyword that’s introduced into the class’s body. When the class loads, these statements are executed. Consider Listing 5.

Listing 5. Initializing arrays of sine and cosine values

Listing 5 declares a Graphics class that declares sines and cosines array variables. It also declares a class initialization block that creates 360-element arrays whose references are assigned to sines and cosines . It then uses a for statement to initialize these array elements to the appropriate sine and cosine values, by calling the Math class’s sin() and cos() methods. ( Math is part of Java’s standard class library. I’ll discuss this class and these methods in a future article.)

Performance trick

Because performance is important to graphics applications, and because it’s faster to access an array element than to call a method, developers resort to performance tricks such as creating and initializing arrays of sines and cosines.

Combining class field initializers and class initialization blocks

You can combine multiple class field initializers and class initialization blocks in an application. Listing 6 provides an example.

Listing 6. Performing class initialization in top-down order

class MCFICIB < static int x = 10; static double temp = 98.6; static < System.out.println("x = " + x); temp = (temp - 32) * 5.0/9.0; // convert to Celsius System.out.println("temp = " + temp); >static int y = x + 5; static < System.out.println("y prettyprint">javac MCFICIB.java

Then run the resulting application:

You should observe the following output:

This output reveals that class initialization is performed in top-down order.

() methods

When compiling class initializers and class initialization blocks, the Java compiler stores the compiled bytecode (in top-down order) in a special method named () . The angle brackets prevent a name conflict: you cannot declare a () method in source code because the < and >characters are illegal in an identifier context.

After loading a class, the JVM calls this method before calling main() (when main() is present).

Let's take a look inside MCFICIB.class . The following partial disassembly reveals the stored information for the x , temp , and y fields:

Field #1 00000290 Access Flags ACC_STATIC 00000292 Name x 00000294 Descriptor I 00000296 Attributes Count 0 Field #2 00000298 Access Flags ACC_STATIC 0000029a Name temp 0000029c Descriptor D 0000029e Attributes Count 0 Field #3 000002a0 Access Flags ACC_STATIC 000002a2 Name y 000002a4 Descriptor I 000002a6 Attributes Count 0

The Descriptor line identifies the JVM's type descriptor for the field. The type is represented by a single letter: I for int and D for double .

The following partial disassembly reveals the bytecode instruction sequence for the () method. Each line starts with a decimal number that identifies the zero-based offset address of the subsequent instruction:

 0 bipush 10 2 putstatic MCFICIB/x I 5 ldc2_w #98.6 8 putstatic MCFICIB/temp D 11 getstatic java/lang/System/out Ljava/io/PrintStream; 14 new java/lang/StringBuilder 17 dup 18 invokespecial java/lang/StringBuilder/()V 21 ldc "x = " 23 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 26 getstatic MCFICIB/x I 29 invokevirtual java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder; 32 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; 35 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 38 getstatic MCFICIB/temp D 41 ldc2_w #32 44 dsub 45 ldc2_w #5 48 dmul 49 ldc2_w #9 52 ddiv 53 putstatic MCFICIB/temp D 56 getstatic java/lang/System/out Ljava/io/PrintStream; 59 new java/lang/StringBuilder 62 dup 63 invokespecial java/lang/StringBuilder/()V 66 ldc "temp = " 68 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; 71 getstatic MCFICIB/temp D 74 invokevirtual java/lang/StringBuilder/append(D)Ljava/lang/StringBuilder; 77 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; 80 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 83 getstatic MCFICIB/x I 86 iconst_5 87 iadd 88 putstatic MCFICIB/y I 91 getstatic java/lang/System/out Ljava/io/PrintStream; 94 new java/lang/StringBuilder 97 dup 98 invokespecial java/lang/StringBuilder/()V 101 ldc "y prettyprint">static int x = 10;

The instruction sequence from offset 5 through offset 8 is equivalent to the following class field initializer:

The instruction sequence from offset 11 through offset 80 is equivalent to the following class initialization block:

static < System.out.println("x = " + x); temp = (temp - 32) * 5.0/9.0; // convert to Celsius System.out.println("temp prettyprint">static int y = x + 5;

The instruction sequence from offset 91 through offset 115 is equivalent to the following class initialization block:

static < System.out.println("y sidebar">

Don't worry about what the bytecode means

The takeaway from this exercise is to see that all code in Listing 6's class field initializers and class initialization blocks is located in the () method, and is executed in top-down order.

How to initialize objects

After a class has been loaded and initialized, you'll often want to create objects from the class. As you learned in my recent introduction to programming with classes and objects, you initialize an object via the code that you place in a class's constructor. Consider Listing 7.

Listing 7. Using the constructor to initialize an object

class City < private String name; int population; City(String name, int population) < this.name = name; this.population = population; >@Override public String toString() < return name + ": " + population; >public static void main(String[] args) < City newYork = new City("New York", 8491079); System.out.println(newYork); // Output: New York: 8491079 >>

Listing 7 declares a City class with name and population fields. When a City object is created, the City(String name, int population) constructor is called to initialize these fields to the called constructor's arguments. (I've also overridden Object 's public String toString() method to conveniently return the city name and population value as a string. System.out.println() ultimately calls this method to return the object's string representation, which it outputs.)

Before the constructor is called, what values do name and population contain? You can find out by inserting System.out.println(this.name); System.out.println(this.population); at the start of the constructor. After compiling the source code ( javac City.java ) and running the application ( java City ), you would observe null for name and 0 for population . The new operator zeroes an object's object (instance) fields before executing a constructor.

As with class fields, you can explicitly initialize object fields. For example, you could specify String name = "New York"; or int population = 8491079; . However, there's usually nothing to gain by doing this, because these fields will be initialized in the constructor. The only benefit that I can think of is to assign a default value to an object field; this value is used when you call a constructor that doesn't initialize the field:

int numDoors = 4; // default value assigned to numDoors Car(String make, String model, int year) < this(make, model, year, numDoors); >Car(String make, String model, int year, int numDoors)

Object initialization mirrors class initialization

Источник

Оцените статью