反射機制中獲取private成員的值

咱們來看下例子:java

@Data
public class Demo {

    public String name;
    private String title;

}

 

public class Test {

    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.lian.demo.Demo");
            Demo demo = (Demo) clazz.newInstance();
            demo.setName("name1");
            demo.setTitle("title1");

            Field[] fields = clazz.getDeclaredFields();
            Arrays.stream(fields).forEach(field -> {
                try {
                    System.out.println("成員變量"+field.getName()+"的值爲:"+field.get(demo));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

執行結果以下:安全

成員變量name的值爲:name1
java.lang.IllegalAccessException: Class com.lian.demo.Test can not access a member of class com.lian.demo.TestDemo with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Field.get(Field.java:390)
	at com.lian.demo.Test.lambda$main$0(Test.java:38)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at com.lian.demo.Test.main(Test.java:31)

說明反射機制中沒法獲取到private成員的值。那到底有沒有辦法獲取到?固然是有。Java反射機制提供的setAccessible()方法能夠取消Java的權限控制檢查。spa

Arrays.stream(fields).forEach(field -> {
                boolean flag = field.isAccessible();
                System.out.println(field.getName() + ":" + flag);
                try {
                    //設置該屬性老是可訪問
                    field.setAccessible(true);
                    System.out.println("成員變量"+field.getName()+"的值爲:"+field.get(demo));
                } catch (IllegalAccessException e) {
                    System.out.println(e.getMessage());
                }
                //還原可訪問權限
                field.setAccessible(flag);
            });

這下沒問題了,能夠獲取到了。setAccessible(true)取消了Java的權限控制檢查,但不是改變方法或字段的訪問權限。code

而對於setAccessible()方法是否會破壞類的訪問規則,產生安全隱患,我在知乎上面看到的一篇回答貌似頗有道理:blog

相關文章
相關標籤/搜索