2015-08-15 127 views
6

我正在學習反思。當我執行下面的代碼:Java反射是可訪問的方法

package main; 

import java.lang.reflect.Field; 

public class Main { 
    public static void main(String[] args) throws NoSuchFieldException, SecurityException { 

     Base firstBase = new Base(); 
     Field firstBaseField = firstBase.getClass().getDeclaredField("protectedBuffer"); 
     System.out.println(firstBaseField.isAccessible()); 

    } 
} 

這是基類:

package main; 

public class Base { 

    private StringBuffer buffer; 
    protected StringBuffer protectedBuffer; 
    public StringBuffer buffer2; 

} 

結果是假的。但是這不是真的,因爲我可以這樣訪問protectedBufferfirstBase.protectedBuffer

+0

我知道我只是在寫String而不知何故它會自動完成StringBuffer。在這種情況下班級是什麼並不重要。 – DPM

回答

6

那是因爲你沒有測試領域protectedBuffer是否可以訪問,當你做firstBaseField.isAccessible();

這裏會發生什麼事是你檢查AccessibleObject值是用於現場的基類。 此標誌不會告訴您,如果字段可由java訪問修飾符訪問,它會告訴您這些修飾符當前是否被忽略。

當你在firstBaseField.isAccessible()上得到錯誤時,它僅僅意味着java訪問規則仍然存在,並且不會被反射機制覆蓋。

setAccessible()

設置accessible標誌此對象指示的布爾值。值爲true表示反射對象在使用時應禁止Java語言訪問檢查。值爲false表示反射對象應強制執行Java語言訪問檢查。

編輯

要測試場是Java的訪問修飾符訪問,你可以嘗試訪問它,趕上IllegalAccessException,就像例如波紋管。

Field field = instance.getClass().getDeclaredField("someField"); 
// IllegalAccessException 
field.get(instance); 
+0

非常感謝。我閱讀了關於可訪問性的內容,但我在發佈問題時暫時忘記了它。所以有一種方法可以理解是直接訪問字段(即使用firstBaseField.variable)。這對我來說並不重要,我只是好奇而已。 – DPM

+0

您可以使用方法Field.getModifiers()https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html#getModifiers--然後檢查您正在查找的修飾符at is public:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Modifier.html – John

+1

實際上,最簡單的方法是嘗試訪問該字段。如果您無法訪問它,則會拋出IllegalAccessException。這將涵蓋受保護和包裝私人案件。 – John

2

你錯誤地理解了這個可訪問的標誌。根據documentation,當可訪問性爲true時,所有訪問檢查都被繞過(您可以使用此字段或方法,並且Java不會檢查它是否公開)。當訪問是錯誤的,訪問檢查工作。而且由於它是用文檔編寫的,所以默認爲false任何AccessibleObject(即使對於public字段或方法)。

1

默認情況下,使用Class#getDeclaredField(String name)檢索到的所有Fieldsaccessible標誌設置爲public字段buffer2也會得到錯誤。

Field類是AccessibleObject一個子類:

默認情況下,反射的物體是訪問。