天天看點

java變量前加private_類中private變量真的private麼?

内容簡介

利用反射機制修改類中的private修飾的變量(當然,在沒有提供setter的情況下)。

本篇主要講述了如何利用反射機制修改類中的一個private變量。下一篇将會展示利用反射機制來違反或者說攻擊單例模式。

利用反射機制破壞單例模式

正文

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

public class PrivateTest {

private int privateInt = 0;

int getPrivateInt()

{

return this.privateInt;

}

}

這裡提供了get方法,用于我們後來的檢測。

ok,現在用于測試的類有了,我們來利用反射的機制嘗試修改PrivateTest類中的privateInt變量。

如果我們寫成這樣:

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());

}

}

運作之後會發現輸出如下:

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的。是以我們做以下修改:

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());

}

}

于是輸出的結果如下:

Before :0

After :3

至此,我們已經成功的修改了類中的private變量的内容。

思考到這裡的時候我很好奇為什麼java會允許這種事情的存在,這種setAccessible的行為是不是破壞了java的封裝性呢?

下一篇要寫的更是利用反射機制成功的破壞掉了單例模式。

剛剛接觸反射和單例,大家多多讨論吧!