应楼主之要求,反编译 public class A{ A a = null; } 后的输出结果: Compiled from "A.java" public class A extends java.lang.Object{ A a;public A(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: aconst_null 6: putfield #2; //Field a:LA; 9: return}Compiled from "A.java" public class A extends java.lang.Object{ A a;public A(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: aconst_null 6: putfield #2; //Field a:LA; 9: return}
Compiled from "A.java" public class A extends java.lang.Object{ A a;public A(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V //调用object里的方法 4: aload_0 //这是什么意思 5: aconst_null 6: putfield #2; //Field a:LA; //看不出来有什么 9: return}
分配了类A的地址空间 与null无关系吧
public class A{ A a = null; } 这只是一个数据结构的定义 你不调用 new A(),对内存没有任何影响。 当你调用 new A()的时候,JVM先在堆里面创建一个对象,里面有一个对象指针字段(就是 A a),不过里面的值是空的,表示是null的。 因此你把这个A a当成一个指针好了,JVM知道的是它是一个指向A类型对象的指针而已如果有如下代码,比如: public class A{ A a = null; public static void main(String args[]){ A xx=new A(); xx.a=new A(); } } 指向main方法时,JVM在堆里面创建了2个对象 第1个对象的成员a因为第二句,指向了第2个对象, 而第2对象的成员a还是空的,没有指向任何对象。
这样用的时候,还没有A的数据结构,为什么可以定义A类型的a变量(A a = null) 只有到加载时,内存里有A的数据结构!在此这前,根本不知道A是什么东西,怎么可以用来定义变量a
public class A{ A a = null; } 加载这个类的时候首先看到的就是A,里面怎么会不知道A是个什么东西呢,A是什么根本不重要。先明确自己想了解到到底是什么问题,编译器负责编译的事 ,jvm负责加载和执行的问题。
public class A{ A a = null; } 中A a = null; 其实是首先在栈中分配了a单元,此时内容为空; 假如 public class A{ A a = null; a=new A(); }则a=new A();在堆中分配了一个单元,然后a是指向了堆中的单元的地址。A a = null;的作用是初始化,方便作为成员变量调用。
在加载A的时候,就遇到了A a = null,但些A的数据结构还不完整啊( 比如在A a后还有其它的变量),JVM此时怎么处理
与是不是null无关系吧
public class A{
A a = null;
}
后的输出结果:
Compiled from "A.java"
public class A extends java.lang.Object{
A a;public A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: aconst_null
6: putfield #2; //Field a:LA;
9: return}Compiled from "A.java"
public class A extends java.lang.Object{
A a;public A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: aconst_null
6: putfield #2; //Field a:LA;
9: return}
Compiled from "A.java"
public class A extends java.lang.Object{
A a;public A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V //调用object里的方法
4: aload_0 //这是什么意思
5: aconst_null
6: putfield #2; //Field a:LA; //看不出来有什么
9: return}
A a = null;
}
这只是一个数据结构的定义
你不调用 new A(),对内存没有任何影响。
当你调用 new A()的时候,JVM先在堆里面创建一个对象,里面有一个对象指针字段(就是 A a),不过里面的值是空的,表示是null的。
因此你把这个A a当成一个指针好了,JVM知道的是它是一个指向A类型对象的指针而已如果有如下代码,比如:
public class A{
A a = null;
public static void main(String args[]){
A xx=new A();
xx.a=new A();
}
}
指向main方法时,JVM在堆里面创建了2个对象
第1个对象的成员a因为第二句,指向了第2个对象,
而第2对象的成员a还是空的,没有指向任何对象。
只有到加载时,内存里有A的数据结构!在此这前,根本不知道A是什么东西,怎么可以用来定义变量a
A a = null;
}
加载这个类的时候首先看到的就是A,里面怎么会不知道A是个什么东西呢,A是什么根本不重要。先明确自己想了解到到底是什么问题,编译器负责编译的事 ,jvm负责加载和执行的问题。
A a = null;
}
中A a = null; 其实是首先在栈中分配了a单元,此时内容为空;
假如 public class A{
A a = null;
a=new A();
}则a=new A();在堆中分配了一个单元,然后a是指向了堆中的单元的地址。A a = null;的作用是初始化,方便作为成员变量调用。
在加载A的时候,就遇到了A a = null,但些A的数据结构还不完整啊( 比如在A a后还有其它的变量),JVM此时怎么处理
你考虑的问题是编译器的问题,不是jvm的问题。
也给hbwhwang 50分
编译的时候由编译器全权负责,我认为编译器把A作为了一种类型存入类型符号表中,在编译到a的时候他会到能用的类型符号表中寻找前面的A类型,一个lookup函数查找,而这个A在类型符号表中的属性就不管了,他可以赋予哪些值也不管了,反正就有null值。我觉得这阶段就是类型检查,编译器完成他的任务但些A的数据结构还不完整啊( 比如在A a后还有其它的变量),JVM此时怎么处理:JVM只管有.class文件就能可以把其加载入内存,即只要不存在编译时错误(静态检查过程)的问题,执行就从main开始,A a = null;定义了一个对象的引用,用到不用到就不知道了