咖啡伴侶

          呆在上海
          posts - 163, comments - 156, trackbacks - 0, articles - 2

          通過反射修改類的私有字段值,調用私有方法

          Posted on 2008-06-21 11:40 oathleo 閱讀(370) 評論(0)  編輯  收藏 所屬分類: Java

          下面這個例子在實際項目中一般都不會這么用,只是用來說明怎么通過反射修改類的私有字段的值.

          有一個類TestData:

          public class TestData {
          ?private String name = "1";
          ?
          ?public String getName() {
          ??return name;
          ?}
          }
          在運行的時候怎么來修改name的值呢?

          public class TestReflection extends TestCase {
          ?public void testSetPrivateField() throws Exception {
          ??TestData data = new TestData();
          ??System.out.println(data.getName());
          ? Assert.assertEquals("1", data.getName());
          ??Field f = data.getClass().getDeclaredField("name");
          ??f.setAccessible(true);
          ??f.set(data, "2");
          ??System.out.println(data.getName());
          ? Assert.assertEquals("2", data.getName());
          ?}
          }
          運行結果:
          1
          2
          其中,最關鍵的代碼是:
          f.setAccessible(true);
          這行代碼把對象data上的name字段設置為public訪問屬性.

          既然私有字段可以這樣訪問,那么,類似的,私有方法也可以這樣調用!
          改一下TestData:

          public class TestData {
          ?private String name = "1";
          ?
          ?public String getName() {
          ??return name;
          ?}
          ?
          ?private void setName(String name) {
          ??this.name = name;
          ?}
          }
          在TestData中增加了私有的setName方法,下面是測試代碼:
          public class TestReflection extends TestCase {?
          ?public void testInvokePrivateMethod() throws Exception {
          ??TestData data = new TestData();
          ??System.out.println(data.getName());
          ? Assert.assertEquals("1", data.getName());
          ??Method m = data.getClass().getDeclaredMethod("setName", String.class);
          ??m.setAccessible(true);
          ??m.invoke(data, "3");
          ??System.out.println(data.getName());
          ? Assert.assertEquals("3", data.getName());
          ?}
          }
          運行結果:
          1
          3
          其中最關鍵的代碼行是:
          m.setAccessible(true);
          它把對象data的setName方法的訪問屬性設置為public.

          那么這樣調用私有方法,訪問私有屬性有什么用處呢?
          在實際項目中,我們會使用很多其它第三方的包,有的時候是通過修改源代碼完成你想要的功能,有的時候,是因為第三方包中僅僅因為某幾個方法的訪問屬性被設置為private,或者只要修改private的字段值即可.這個時候,用這種反射的方法就可以很容易實現了.

          另外一個場景就是從系統架構層來考慮數據封裝.例如系統有一些元數據類,99%的情況下,我們只是提供get方法供其它應用層獲得字段的值,如果把修改的 set方法也提供出去,那么可能會影響到系統的可維護性.而在系統運行期間,又很難避免的要修改這些元數據的值.這種情況下,也可以通過這種反射的方式來 實現.

          主站蜘蛛池模板: 舞阳县| 邻水| 临西县| 修文县| 兴宁市| 盐津县| 东海县| 晋宁县| 青阳县| 青河县| 石楼县| 陆河县| 化州市| 唐山市| 临西县| 高唐县| 定远县| 八宿县| 麻江县| 凤山市| 石景山区| 石嘴山市| 庆城县| 会泽县| 文成县| 瑞金市| 香河县| 邵阳市| 温州市| 清河县| 个旧市| 苏尼特右旗| 稻城县| 潜山县| 大姚县| 沿河| 建瓯市| 永川市| 唐山市| 涿鹿县| 咸宁市|