Java中继承的成员会编译到子类.class文件吗?还是仅保留超类链接?
关于Java继承成员与子类.class文件的疑问解答
嘿,这个问题问到点子上了,刚好涉及Java继承底层的核心逻辑,咱们把它掰扯清楚:
1. 成员会被编译到子类的.class文件中吗?
答案很明确:不会。Java的继承机制依赖的是动态链接,子类并不会把超类的成员复制一份塞进自己的字节码里,只会在需要访问这些成员时,通过符号引用去关联超类的对应定义,直到类加载的解析阶段,才会把这些符号引用替换成能直接访问的内存地址引用。
2. 细分:静态/实例、方法/字段的具体情况
不管是静态成员还是实例成员,是方法还是字段,规则都是统一的——子类.class里不会包含任何继承来的成员的字节码:
- 实例方法与字段:子类的字节码只存放自己定义的实例成员。当你在子类里调用超类的实例方法时,字节码会生成
invokevirtual(普通实例方法)或invokespecial(比如构造方法)指令;访问超类实例字段时,会用getfield/putfield指令,这些指令都会明确指向超类的对应成员。 - 静态方法与字段:访问超类静态成员时,字节码会生成
invokestatic(静态方法)、getstatic/putstatic(静态字段)指令,同样是直接引用超类的定义,不会把静态成员复制到子类中。
举个实际例子验证
写两个简单的类:
超类Parent.java:
public class Parent { public String parentField = "I'm parent"; public void parentMethod() {} public static String staticParentField = "Static parent"; public static void staticParentMethod() {} }
子类Child.java:
public class Child extends Parent {}
编译后,用javap -v Child.class查看子类的字节码,你会发现Child的字节码里完全没有上述父类成员的定义,只有默认构造方法和指向Parent类的符号引用。
至于为什么我们能在子类里直接调用这些成员?那是Java编译器帮我们做了“语法糖”转换,把这些访问操作转换成了对超类成员的引用,而JVM在执行时会顺着类的继承关系去超类中查找对应的成员。
另外提个例外:超类的私有成员。子类根本无法继承私有成员,所以子类的.class里连对它们的引用都不会有,编译器直接就禁止子类访问私有成员(反射是运行时的特殊情况,不在编译阶段考虑)。
内容的提问来源于stack exchange,提问作者xingbin
相关产品推荐
相关产品推荐

