2011-02-27 59 views
3

爲什麼這段代碼返回「class java.lang.Object」?反映嵌套匿名類的Java

Object a = new Object() { 
    public Object b = new Object(){ 
    public int c; 
    }; 
}; 

System.out.println(a.getClass().getField("b").getType()); 

爲什麼內心型會迷路?我如何反映c字段?

編輯:

這一個工程(如在一些答案指出):

a.getClass().getField("b").get(a) ... 

但我必須調用一個getter,有沒有什麼辦法,以反映與只反射元數據c ?

+0

內部類型** IS **對象。這是匿名擴展對象! – Nishant 2011-02-27 17:04:14

回答

5

b由於被聲明爲Object

public Object b = ...; 

有由變量(運行時類型)所引用的對象的類型變量(靜態型)和類型之間的區別。

Field.getType()返回該字段的靜態類型。

如果你想獲得由現場引用的對象的運行時類型,您需要訪問該對象並在其上調用getClass()(因爲a被聲明爲Object,因此b是不可見,因爲其成員必須使用反射來訪問它):

System.out.println(
    a.getClass().getField("b").get(a).getClass()); 

UPDATE:不能反映c而不訪問對象的包含它的實例。這就是爲什麼這些類型被稱爲匿名 - 包含c的類型沒有名稱,因此您不能將字段b聲明爲該類型的字段。

+0

所以是'a',它不是java.lang.Object類型 – Marcus 2011-02-27 17:04:55

+3

「ab」不合法,因爲b字段不存在於類型java.lang.Object中 – Marcus 2011-02-27 17:06:39

+0

您不能以這種方式訪問​​b,因爲只是編譯器的一個普通對象。您會收到「b無法解析或不是字段」的錯誤。 – Boris 2011-02-27 17:07:48

1

爲什麼內心型會迷路?

因爲您正在獲取字段「b」(對象)的類型類型,而不是您將實例分配給「b」的匿名內部類的類型。

如何反映c字段?

您可以使用此

System.out.println(a.getClass().getField("b").get(a).getClass().getField("c")); 

代替。這會得到字段「b」的值,它是類,但只有在「b」保證不爲空時纔有效。

這樣做似乎表明一個糟糕的設計,可能有其他方法來存檔你想要做什麼。但不知道目的,這是我能夠回答的一切。

+0

嗯,我沒有任何這個代碼的實際用途,我只是偶然發現它,想知道它爲什麼表現得像它的行爲。所以沒有任何方法可以只用元數據反映c(即不使用get(a))? – Marcus 2011-02-27 17:08:11

+0

好吧,好奇心總是好:)據我所知,沒有辦法用匿名內部類,因爲你沒有辦法得到這些類java.lang.Class-instance沒有一個匿名類的實際實例(顯然除了Class.forName()等) – Boris 2011-02-27 17:11:27

3

讓我們來看看仔細這一行:

System.out.println(a.getClass().getField("b").getType()); 

首先,你拿的a變量。它是Object的一些匿名子類。我們稱之爲MyClass$1。好的,到目前爲止這麼好。

接下來,您調用getClass()方法。它返回a的類,即MyClass$1類的描述。儘管如此,這個描述並不依賴於那個類的任何特定的實例。這個類對於所有的實例都是一樣的,不管它是a還是別的(除非使用不同的類加載器)。然而,在這種特殊情況下,只能有一個實例,因爲該類是匿名的,但機制仍然相同。

現在,從課堂上,您將獲得字段b。由於課程並不直接與任何這種情況聯繫在一起,因此該字段與a無關。這只是對MyClass$1類別的字段a究竟是什麼的描述。

現在你得到它的類型。但由於它不受任何實例限制,因此無法知道運行時類型。事實上,如果班級不是匿名的,則可以有多個MyClass$1實例,每個實例在a中具有不同的值。或者你根本沒有實例。所以getType()唯一可能告訴你的是b的聲明類型,這正是它所做的。 b字段實際上可能是null,那麼結果就是Object

Field類提供了get()方法來實際訪問某個對象的特定領域,如:

System.out.println(a.getClass().getField("b").get(a).getClass()); 

現在你喜歡的東西MyClass$1$1,這是匿名類的名稱對象b字段a實例