2012-04-13 28 views
2

我想澄清一些事情。使用「普通」Java反射技術(不使用庫)afaik不可能獲得對私有字段的引用(我的意思是java.lang.reflect.Field對象,不包含字段值)。參考私人領域使用番石榴反射

舉例來說,如果我有這個類:

public class MyClass { 
    private String field1; 
} 

如果我嘗試執行此:

Field field = MyClass.class.getField("field1"); 

我會得到一個NoSuchFieldException異常,符合市場預期。

隨着Guava Reflection library,如果我嘗試執行此:

Object o = new MyClass(); 
Property property = Properties.getPropertyByName(o, "field1"); 
Field f = property.getField(); 

我得到以下異常:

java.lang.IllegalStateException: Unknown property: field1 in class MyClass 

同時這也在意料之中。但是,如果我添加一個getter方法,如下所示:

public class MyClass { 
    private String field1; 
    public String getField1() {return field1;} 
} 

然後番石榴反射代碼正在工作。 我必須承認我對此有點遺憾。我明白,反射庫可以使用getter來返回私有實例變量的值,但是Field對象本身只是因爲存在getter而已?有人有一個想法如何發生?

+1

我不能完全肯定,但你嘗試過'場場= MyClass的訪問。 class.getDeclaredField( 「字段1」);'?這可能是區別... – user219882 2012-04-13 23:10:33

+0

是的,唯一的問題是,getDeclaredField將只給我這個類聲明的字段,而不是任何祖先。我看到如何繞過這個問題(遍歷祖先),但看起來有點像書寫枯燥的樣板代碼... – Sergio 2012-04-13 23:45:16

+2

無標籤「番石榴」,因爲這個問題與番石榴無關。 – 2012-04-14 14:26:09

回答

3

您可以使用標準的Java反射,這可能是私人領域是什麼番石榴引擎蓋下做反映:

Class<?> c = ... some class ... 
Field field = c.getDeclaredField("name"); 
field.setAccessible(true); 
Object value = field.get(object); 

getDeclaredField可以獲取私有字段。需要 setAccessible以防止安全問題。

無論如何,作爲一種最佳實踐,請考慮只對公衆成員進行反思,所以如果可能的話,請與getter/setters一起工作。

希望有所幫助。

+0

謝謝,現在我發現它是可能的,但仍然比在Guava中對Field對象的訪問依賴於getter的存在感到困惑。 – Sergio 2012-04-13 23:20:03

+0

我自己並沒有使用番石榴,但這很可能發生了什麼:在Java中,「屬性」通常意味着一個JavaBean樣式的屬性,它基於一個訪問器/增變器對(「getName」和「setName」 )。通過構建一個名爲「name」的屬性,Guava可能只是根據JavaBean屬性約定來查找訪問器/增量器,而不是字段。 – Torious 2012-04-13 23:40:15

+0

我剛剛意識到getDeclaredField的問題是它不會回答由祖先類聲明的字段。 – Sergio 2012-04-13 23:47:03

1

Field延伸AccesibleObject,它有一個方法setAccessible(),允許您訪問專用字段的值。

番石榴反射(注意,這個庫是番石榴不同)是使你的私人領域像Property.getFieldValue()方法