为什么函数“display()”会自动放在构造函数中

时间:2014-11-26 06:27:01

标签: java

以下代码中我有两个类几乎什么都不做。当检查“类TestBed”的反编译代码时,“int val = tb.display()”会自动放入构造函数中。这是怎么回事?

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");
    }

}

使用反编译器反编译“TestBed.class”后出现代码

/* 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;
    }
}

6 个答案:

答案 0 :(得分:2)

这是因为* .class文件的格式。当您将* .java文件编译为* .class文件时,将以您的字段var的方式初始化的所有实例字段(这是:T myVar = myValue)将在构造函数中初始化& #39;代码。

类格式的简短且不完整的描述

类格式由不同类型的"结构"组成,其中两个是字段结构(您的字段var已注册)和方法结构(代码仅存在于内部属性"代码")下的这种结构。

字段结构没有代码空间(将初始化var:int val = tb.display();的代码)因此需要将其放在"代码中#34;与构造函数对应的方法结构的属性。

请查看Java Virtual Machine Specification, Ch. 4以获取更多详细信息(尝试用几句话来解释所有内容会太复杂)

答案 1 :(得分:1)

您的字段val的值等于tb.display。所有字段都使用默认值(int为0)和构造函数中的其他预定义用户值进行初始化。因此在构造函数中调用方法tb.display

答案 2 :(得分:1)

运行时上面的代码给出Null Pointer Exception,因为tb变量尚未初始化。

由于类级变量的初始化必须在类实例化上进行,编译器会将代码放在构造函数中。

尝试使用某个参数定义显式构造函数,并通过以下更改尝试另外一种方法

static TestBed tb;

static int val = tb.display();

答案 3 :(得分:0)

我认为这种行为没有任何特殊原因。

但是,通常情况下,变量在构造函数内部实例化,而反编译器可能只是使用此标准。在这种情况下,两段代码的效果应完全相同。

无论如何,val将设置为tb.display();

答案 4 :(得分:0)

实例变量初始化实际上是由编译器放在构造函数中的。

请参阅here

答案 5 :(得分:0)

您的变量TestBed tb尚未初始化,但您正在调用int val = tb.display();,这将引发异常。您没有获得异常的原因是因为您没有在TestBed中的任何位置实例化类main(),只需将代码更改为: -

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

你会得到nullpointer exception

你在反编译器中获得该代码的原因是因为这一点,从java tutorial读取(找不到javadocs源的链接:))

  

Java编译器自动生成实例字段初始化代码,并将其放在类的构造函数或构造函数中。初始化代码按照它在源代码中出现的顺序插入到构造函数中。

因此编译器将int val= tb.display()分解为

int val;

TestBed(){
val=tb.display();
}