Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Class and object initialization

Learn how to prepare classes and objects for use in an executing program

  • Print
  • Feedback

Page 8 of 9

oid2.b = true
oid2.by = 1
oid2.c = A
oid2.d = 1.2
oid2.f = 3.4
oid2.i = 2
oid2.l = 3
oid2.s = 4
oid2.st = abc


What is responsible for executing the object field initializers? Would you believe that the constructor is? As strange as it might seem, the compiler inserts byte code instructions into a class's constructor to execute object field initializers. But there's more: When you look at a constructor from the JVM's perspective, you no longer see a constructor. Instead, you see what the JVM refers to as an <init> method.

During class compilation, the compiler generates an <init> method for each of that class's constructors. If that class contains no constructors (as in ObjectInitializationDemo2), the compiler generates an <init> method that matches the default no-argument constructor. It is important to realize that each constructor has its own corresponding <init> method and that the compiler places byte code instructions, apart from the instructions you specify (via Java source code), into that method. Some of those instructions serve to execute object field initializers.

Take a close look at Listing 10. You cannot see its presence, but a constructor does exist. If you could see that constructor, it would probably look like the following code fragment:

ObjectInitializationDemo2 ()
{
}


That's right! The constructor would appear empty. Suppose you disassemble ObjectInitializationDemo2's class file. In that disassembly, you would encounter a no-argument <init> method that matches the default no-argument constructor. And what instructions would you find in that method? Take a look at Listing 11:

Listing 11. ObjectInitializationDemo2's no-argument <init> method

 0        aload_0
 1        invokespecial java/lang/Object/<init>()V
 4        aload_0
 5        iconst_1
 6        putfield ObjectInitializationDemo2/b Z
 9        aload_0
10        iconst_1
11        putfield ObjectInitializationDemo2/by B
14        aload_0
15        bipush 65
17        putfield ObjectInitializationDemo2/c C
20        aload_0
21        ldc2_w #1.200000
24        putfield ObjectInitializationDemo2/d D
27        aload_0
28        ldc #3.400000
30        putfield ObjectInitializationDemo2/f F
33        aload_0
34        iconst_2
35        putfield ObjectInitializationDemo2/i I
38        aload_0
39        ldc2_w #3
42        putfield ObjectInitializationDemo2/l J
45        aload_0
46        iconst_4
47        putfield ObjectInitializationDemo2/s S
50        aload_0
51        ldc "abc"
53        putfield ObjectInitializationDemo2/st Ljava/lang/String;
56        return


Apart from Listing 11's byte code instructions executing ObjectInitializationDemo2's object field initializers, a close examination of Listing 11 reveals some interesting items about how Java works:

  • Note the aload_0 instruction. That instruction pushes an address onto a stack. And what address does that instruction push? The current object address -- as keyword this represents in source code. The invokespecial and putfield instructions pop that address from the stack and use the address to identify the proper object when making a call to an object method or writing to an object field.
  • Note the invokespecial java/lang/Object/<init>()V instruction. That instruction calls the default no-argument constructor -- to be precise, the default no-argument <init> method -- in the Object superclass. (Remember keyword super's use in calling a superclass constructor? You are seeing how Java uses that keyword at the byte code level.)
  • Note the location of invokespecial java/lang/Object/<init>()V. It is no accident that the compiler places that instruction as the second instruction (after aload_0) in the default no-argument <init> method. In accordance with the way Java works, a constructor must first either call another constructor in the same class or a constructor in its superclass. If a constructor does not explicitly call another constructor in the same class (via this) or a constructor in a superclass (via super), the compiler generates byte code instructions that are the equivalent of placing super (); at a constructor's start.


We will explore the second and third items in the above list later in this section, when we examine object initialization and class hierarchies. But first, we need to explore object field initializers and forward references, along with object block initializers.

  • Print
  • Feedback

Resources