4

Here is the following code where I have two classes practically doing nothing. When the decompiled code of the "class TestBed" is checked "int val = tb.display()" gets placed in constructor automatically. How is this happening ?

class TestBed
{
    int display()
    {
        return 100;
    }

    TestBed tb;

    int val = tb.display(); /* will get placed in constructor 
                               automatically. But how? */
}


public class DeleteThis {
    public static void main(String[] args) {
        System.out.println("printing");
    }

}

After decompiling "TestBed.class" using decompiler following code appears

/* Following is decompiled code */
class TestBed
{

    TestBed tb;
    int val;

    TestBed()
    {
        val = tb.display(); /* How int val = tb.display() gets placed 
                               in constructor automatically */
    }

    int display()
    {
        return 100;
    }
}
NoobEditor
  • 15,563
  • 19
  • 81
  • 112

6 Answers6

2

That's because of the format of the *.class file. When you compile a *.java file into a *.class file, all instance fields that are initialized in the way your field var are (this is: T myVar = myValue) are going to be initialized in the constructor's code.

A brief and incomplete description of the class format:

A class format is made up of different kind of "structures", two of them are the field structure (where your field var is registered) and the method structure (code lives only inside this kind of structure under the attribute "code").

The field structure doesn't have room for code (the code that would initialize you var: int val = tb.display();) so it needs to be put inside the "code" attribute of the method structure that corresponds to the constructor.

Have a look at the Java Virtual Machine Specification, Ch. 4 for more details (trying to explain everything here in few words would be too complicated)

morgano
  • 17,210
  • 10
  • 45
  • 56
1

Your field val has value equals tb.display. All fields initialize with default value (0 for int) and other predefined user value at constructor. So method tb.display is called in constructor.

Sergii Lagutin
  • 10,561
  • 1
  • 34
  • 43
1

Run time the above code gives Null Pointer Exception since the tb variable has not been initialized.

As the initialization of Class level variables has to happen on the class instantiation, the compiler places the code in the constructor.

Try defining an explicit constructor with some argument and also try one more approach by below change

static TestBed tb;

static int val = tb.display();
Yusuf Kapasi
  • 577
  • 2
  • 9
0

I don't think there is any particular reason for this behavior.

Typically, though, variables are instantiated inside of the constructor and the decompiler is probably just using this standard. The effect of both segments of code, in this case, should be exactly the same.

Regardless, val will be set to tb.display();.

James Taylor
  • 6,158
  • 8
  • 48
  • 74
  • Hey, I haven't instantiated anything here, and during instantiation all variables placed outside constructor will be given null or 0 depending on their types, and all those who are placed inside constructor will be assigned the given values. But here I am just calling display() method from TestBed tb and for some reason tb.display() gets placed inside the constructor. What is the reason? – priyank jain Nov 26 '14 at 06:40
  • @priyankjain No, you're using `display()` to initialize `val`, which is an instance variable so the initialization has to happen at construction time. – user207421 Nov 26 '14 at 06:48
  • 1
    Variables themselves would be set to 0 or null, but not if they are already being set to something. In both cases `val` would equal 100, no matter where you place the code. – James Taylor Nov 26 '14 at 06:49
0

The instance variable initialization is actually put in the constructor(s) by the compiler.

See here

Community
  • 1
  • 1
Hanzallah Afgan
  • 716
  • 6
  • 23
0

Your variable TestBed tb is not initialized yet you are calling , int val = tb.display(); which will throw exception. The reason you are not getting exception is because you are not instantiating the class TestBed anywhere in the main() , the moment you change code to :-

public class DeleteThis {
   public static void main(String[] args) {
     TestBed tb=new TestBed();
     System.out.println("printing");
    }

You wil get nullpointer exception

And the reason why you get that code in decompiler is because of this, reading from a java tutorial (could not find the link for javadocs source :))

The Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code.

hence the compiler breaks int val= tb.display() into

int val;

TestBed(){
val=tb.display();
}
Mustafa sabir
  • 4,130
  • 1
  • 19
  • 28
  • It will compile. `tb` gets default initialized to `null`. – Radiodef Nov 27 '14 at 22:54
  • yes thats true, but in the next line OP writes `int val = tb.display();` , since tb is initialized to `null` by default you cant call methods on it like `tb.display()` , and since compiler wont do `tb= new TestBed()` , it should give null pointer exception:) – Mustafa sabir Nov 28 '14 at 07:22
  • That is different from not compiling, though. – Radiodef Nov 28 '14 at 07:29