Java 为什么要使用“函数”;显示();自动放置在构造函数中

Java 为什么要使用“函数”;显示();自动放置在构造函数中,java,Java,下面是我有两个类实际上什么都不做的代码。当选中“类测试床”的反编译代码时,“int val=tb.display()”将自动放入构造函数中。这是怎么发生的 class TestBed { int display() { return 100; } TestBed tb; int val = tb.display(); /* will get placed in constructor

下面是我有两个类实际上什么都不做的代码。当选中“类测试床”的反编译代码时,“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;
    }
}

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

我认为这种行为没有什么特别的原因

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


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

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


请参见

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

对课程格式的简要且不完整的描述

类格式由不同类型的“结构”组成,其中两种是字段结构(在其中注册了字段
var
)和方法结构(代码仅位于这种结构的“code”属性下)

字段结构没有空间容纳代码(用于初始化您的代码var:
int val=tb.display();
),因此需要将其放入与构造函数对应的方法结构的“code”属性中


查看以获取更多详细信息(尝试用几句话解释这里的所有内容会太复杂)

运行时由于tb变量尚未初始化,上述代码会出现空指针异常

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

尝试用一些参数定义一个显式构造函数,并通过下面的更改尝试另一种方法

static TestBed tb;

static int val = tb.display();

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

public class DeleteThis {
   public static void main(String[] args) {
     TestBed tb=new TestBed();
     System.out.println("printing");
    }
您将得到
nullpointer异常

您在反编译器中获得该代码的原因就是因为这样,从a读取(找不到javadocs源代码的链接:)

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

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

int val;

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

嘿,我在这里并没有实例化任何东西,在实例化过程中,放置在构造函数外部的所有变量都将根据其类型被赋予null或0,并且所有放置在构造函数内部的变量都将被赋予给定的值。但在这里,我只是从测试台tb调用display()方法,出于某种原因,tb.display()被放置在构造函数中。原因是什么?@priyankjain否,您正在使用
display()
初始化
val
,这是一个实例变量,因此初始化必须在构造时进行。变量本身将被设置为0或null,但如果它们已经被设置为某个值,则不会。在这两种情况下,
val
将等于100,无论您将代码放置在何处。它将编译
tb
将默认值初始化为
null
。是的,这是真的,但在下一行OP写入
int val=tb.display(),因为默认情况下tb被初始化为
null
,所以您不能像
tb.display()
那样调用它的方法,而且由于编译器不会执行
tb=new TestBed()
,所以它应该给出与不编译不同的null指针异常:)。