我经历过这样的事情:
Do subclasses inherit private fields?
但我还是很困惑..。
我说的是只继承而不访问。我知道它们在类外是不可见的。
但是这个子类的对象在超类中有自己的私有成员副本吗?
例如..。
class Base {
private int i;
}
class Derived extends Base {
int j;
}现在,
Base b = new Base();
Derived d = new Derived();int的大小是4
现在,
B的大小是4,d的大小是8吗?
或
%d的大小也将仅为4?
当然,当我说b和d而不是引用时,我指的是堆上的对象。
更新:我刚刚在南华早报上读到凯西·塞拉和伯特的书……上面说他们不是遗传的.我发布了这个更新,因为仍然有一群人说是的…
发布于 2013-01-04 00:17:47
是的,子类的实例将拥有父类的私有字段的副本。
然而,它们对于子类是不可见的,因此访问它们的唯一方法是通过父类的方法。
发布于 2013-01-04 00:29:00
根据JVM规范,class文件是这样构建的:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}super_class字段由以下内容组成:
‘对于类,super_class项的值必须为零,或者必须是constant_pool表的有效索引。如果super_class项的值不为零,则该索引处的constant_pool条目必须是CONSTANT_Class_info (§4.4.1)结构,表示该类文件定义的类的直接超类。无论是直接超类还是它的任何超类都不能在其ClassFile结构的access_flags项中设置ACC_FINAL标志。
如果super_class项的值为零,那么这个类文件必须表示类对象,它是唯一没有直接超类的类或接口。
对于接口,super_class项的值必须始终是constant_pool表的有效索引。该索引处的constant_pool条目必须是表示类对象的CONSTANT_Class_info结构。
更有趣的是fields[]部分:
Each value in the fields table must be a field_info (§4.5) structure giving a complete description of a field in this class or interface. The fields table includes only those fields that are declared by this class or interface. It does not include items representing fields that are inherited from superclasses or superinterfaces.
因此,编译后的类不包含继承的字段。另一方面,当创建一个对象时,private超级域在内存中。为什么?让我们想象一下这个例子:
classs A {
int a;
A(int a) {
this.a = a;
}
void methodA() {
System.out.println("A is: " + a);
}
}
classs B extends A {
int b;
B(int b) {
super(10);
this.b = b;
}
void methodB() {
super.methodA();
System.out.println("B is: " + b);
}
}输出应该是:A is: 10 \n B is ...。
发布于 2013-01-04 00:24:03
两者都不是-对象的大小包含一些开销。但是派生的会比基础占用更多的空间。
运行快速测试,看起来Base的大小约为20字节,而派生的大小约为28字节。请注意,这些结果在不同的JVM上可能会有所不同。
public static void main(String[] args) throws InterruptedException {
int size = 500000;
double mem;
mem = Runtime.getRuntime().freeMemory();
Base[] base = new Base[size];
for (int i = 0; i < size; i++) {
base[i] = new Base();
}
System.out.println((mem - Runtime.getRuntime().freeMemory()) / size);
System.gc();
Thread.sleep(100);
System.gc();
mem = Runtime.getRuntime().freeMemory();
Derived[] derived = new Derived[size];
for (int i = 0; i < size; i++) {
derived[i] = new Derived();
}
System.out.println((mem - Runtime.getRuntime().freeMemory()) / size);
}https://stackoverflow.com/questions/14142737
复制相似问题