以下代码中我有两个类几乎什么都不做。当检查“类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;
}
}
答案 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();
}