2013-01-03 49 views
3

我已經經歷了這樣:superClass的私有成員是否繼承了子類... Java?

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 be 8

d的大小也將只有4?

當然,我說的是堆上的對象,當我說b和d而不是引用時。

更新:我剛剛在凱西塞拉利昂&伯特的SCJP圖書閱讀...它說,他們不是繼承....我張貼了這個更新,因爲還是有人說一堆...是

+0

'private'成員不是繼承的,而是存在於父級(super)的實例化對象中。你的問題實際上是關於陰影(我認爲?你似乎在談論不適用於Java的對象的大小)。請參閱:http://stackoverflow.com/questions/3501060/can-parent-and-child-class-in-java-have-same-instance-variable –

+0

你能否提供確切的文字說明他們沒有被遺傳?在這一點上,我認爲在術語方面存在混淆。根據Java規範,子類不會「繼承」其超類的私有成員,但是它使用非常嚴格的繼承概念,這對Java規範很有用。這個子類的實例肯定會有它自己的實例。所以,從這個意義上講,在你的問題中使用的意義,它們是繼承的。 – Nimrand

+0

@Nimrand確切的文字是:'當一個成員被聲明爲private時,一個子類不能繼承它。'在私人成員 – Sam

回答

6

是的,子類的實例將具有父類的專用字段的副本。

然而,它們對於子類是不可見的,所以訪問它們的唯一方法是通過父類的方法。

0

是的,派生類將擁有基類的私有字段。如果Derived定義了公共getter和setter,那麼您將能夠使用派生類中的該字段使用它。

可否 B的大小是4 和d的大小爲8 或 尺寸d的也將是隻有4?

它是Java而不是C.您無法輕鬆估計堆中對象的大小。它會比4或8個字節更大。

1

無論 - 對象的大小包括一些開銷。但派生將需要比基地更多的空間。

運行一個快速測試,它看起來像一個基地的大小約爲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); 
} 
3

由於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項的值必須要麼是零或必須是常量池表中的有效索引。如果super_class項的值不爲零,那麼該索引處的constant_pool條目必須是一個CONSTANT_Class_info(§4.4.1)結構,該結構表示由此類文件定義的類的直接超類。直接超類或其任何超類都不能在其ClassFile結構的access_flags項中設置ACC_FINAL標誌。

如果super_class項的值爲零,那麼這個類文件必須表示類Object,唯一沒有直接超類的類或接口。

對於接口,super_class項的值必須始終是constant_pool表中的有效索引。該指數在constant_pool條目必須是代表類CONSTANT_Class_info結構Object.`

更有趣的是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.

所以編譯的類不包含繼承的字段。另一方面,當創建一個對象時,超級字段在內存中。爲什麼?讓我們想象一下例子:

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 ...

+0

一節的第1章「聲明和訪問控制」中要完全誠實,這個詳細的解釋有點過於複雜,以回答原始問題,但提供了關於Java內部工作原理的大量信息。解釋中用於類頭結構的+1。 – PSIXO

0

不,私人領域被設計爲可以在其聲明的類上訪問。讓他們在課外(包括派生類)進入的唯一途徑是通過公共方法。

如果要使基類中的成員由派生類繼承,請使用「protected」而不是private。代碼應該是:

class Base { 
    protected int i; 
} 

class Derived extends Base { 
    int j; 
} 

「受保護的」訪問修飾符允許成員被繼承併爲其分配了自己的訪問修飾符。

+0

你是絕對正確的......但我們所說的是繼承他們而不是訪問他們。 – Sam

+0

在這種情況下,如果要將基類成員繼承到派生類,請將基類中的成員聲明爲「protected」 – winux