類中private變量真的private麼?

內容簡介

利用反射機制修改類中的private修飾的變量(固然,在沒有提供setter的狀況下)。
本篇主要講述瞭如何利用反射機制修改類中的一個private變量。下一篇將會展現利用反射機制來違反或者說攻擊單例模式。
利用反射機制破壞單例模式java

正文

首先,咱們有一個包含private類型變量的類。segmentfault

public class PrivateTest {
    private int privateInt = 0;
    int getPrivateInt()
    {
        return this.privateInt;
    }
}

這裏提供了get方法,用於咱們後來的檢測。測試

ok,如今用於測試的類有了,咱們來利用反射的機制嘗試修改PrivateTest類中的privateInt變量。this

若是咱們寫成這樣:code

import java.lang.reflect.Field;

public class Test 
{
    
    public static void main(String args[])
    {    
        PrivateTest privateTest = new PrivateTest();
        System.out.println("Before :" + privateTest.getPrivateInt());
        Class pClass = privateTest.getClass();
        try
        {
            Field field = pClass.getDeclaredField("privateInt");
            field.set(privateTest, 3);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        System.out.println("After :" +privateTest.getPrivateInt());
    }
}

運行以後會發現輸出以下:get

Before :0
java.lang.IllegalAccessException: Class Test can not access a member of class PrivateTest with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
    at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
    at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
    at java.lang.reflect.Field.set(Unknown Source)
    at Test.main(Test.java:17)
After :0

也就是說修改失敗了,緣由很明顯,由於變量是private的。因此咱們作如下修改:it

import java.lang.reflect.Field;

public class Test 
{
    
    public static void main(String args[])
    {    
        PrivateTest privateTest = new PrivateTest();
        System.out.println("Before :" + privateTest.getPrivateInt());
        Class pClass = privateTest.getClass();
        try
        {
            Field field = pClass.getDeclaredField("privateInt");
            field.setAccessible(true);//新增的代碼
            field.set(privateTest, 3);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("After :" +privateTest.getPrivateInt());
    }
}

因而輸出的結果以下:io

Before :0
After :3

至此,咱們已經成功的修改了類中的private變量的內容。
思考到這裏的時候我很好奇爲何java會容許這種事情的存在,這種setAccessible的行爲是否是破壞了java的封裝性呢?
下一篇要寫的更是利用反射機制成功的破壞掉了單例模式。class

剛剛接觸反射和單例,你們多多討論吧!import

相關文章
相關標籤/搜索