构造器
Java代码里面用new生成一个对象的时候,JVM会执行用来请求内存的 new 指令,以及用来调用构造器的 invokespecial 指令。通过使用javap命令查看生成的字节码,就能清晰的看到。
// Foo foo = new Foo(); java代码
0 new Foo //申请内存
3 dup
4 invokespecial Foo() //调用构造器
7 astore_1
如果一个类没有定义任何构造器的话,就不会有第二个操作了吗?答案是否定的,及时类中没有任何构造器,Java编译器会自动添加一个无参构造器,如果没有继承其他类,父类就是Object,所以会自动调用Object的无参构造函数。
// Foo类构造器会调用其父类Object的构造器
public Foo();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
代码验证
写两个简单的类来验证。
public class ParentClazz {
private String name;
}
public class ChildClazz extends ParentClazz {
private String childName;
}
编译代码,并查看字节码
#javac ParentClazz.java ChildClazz.java
#javap -v ParentClazz.class
public micreeson.learning.jvm.clazz.ParentClazz();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
#javap -v ChildClazz.class
public micreeson.learning.jvm.clazz.ChildClazz();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method micreeson/learning/jvm/clazz/ParentClazz."<init>":()V
4: return
LineNumberTable:
line 4: 0
成员变量
通过 new 指令新建出来的对象,它的内存其实涵盖了所有父类中的实例字段。也就是说,虽然子类无法访问父类的私有实例字段,或者子类的实例字段隐藏了父类的同名实例字段,但是子类的实例还是会为这些父类实例字段分配内存的
这点可以使用jvisualvm来查看子类对象的成员来验证