首页 > 代码库 > 反射的应用

反射的应用

最近在公司搞一些llt的白盒测试用例,经常需要使用到反射进行实例的替换,将实际的类替换为伪装代理类来进行数据的打桩。这个时候会遇到很多需要访问私有属性的情况,甚至需要访问到final的属性,这个时候,需要进行一些特殊的处理。

先来个示例的bean类:

 1 package com.iwuyc.test.powermockito.powermockito.test;
 2 
 3 import java.util.concurrent.atomic.AtomicInteger;
 4 
 5 /**
 6  * Hello world!
 7  *
 8  */
 9 public class DemoBean
10 {
11     private static final AtomicInteger privateStaticFinalField = new AtomicInteger();
12     
13     private static AtomicInteger privateStaticField = new AtomicInteger();
14     
15     private AtomicInteger privateField = new AtomicInteger();
16 
17     public static AtomicInteger getPrivatestaticfinalfield()
18     {
19         return privateStaticFinalField;
20     }
21 
22     public static AtomicInteger getPrivateStaticField()
23     {
24         return privateStaticField;
25     }
26 
27     public AtomicInteger getPrivateField()
28     {
29         return privateField;
30     }
31 
32     
33 }

 

·访问private修饰的属性:

 1     @Test
 2     public void testGetPrivateField() throws Exception
 3     {
 4         DemoBean demoBean = new DemoBean();
 5         AtomicInteger valOld = demoBean.getPrivateField();
 6         
 7         Field privateField = DemoBean.class.getDeclaredField("privateField");
 8         //修改可访问的权限,对于私有的不可访问的,我们可以通过设置改值进行强制访问
 9         //该方法不仅仅是只有Field的实力中存在,在Method、Construct中也存在该方法
10         //也就是说,访问私有的Method跟私有的Construct也是可以进行强制访问的
11         privateField.setAccessible(true);
12         
13         privateField.set(demoBean, new AtomicInteger());
14         
15         AtomicInteger valNew = demoBean.getPrivateField();
16         
17         Assert.assertFalse("Two values is equals,but that was not my expected.",valOld.equals(valNew));
18     }

·访问private static修饰的属性

 1     @Test
 2     public void testGetPrivateStaticField() throws Exception
 3     {
 4         AtomicInteger valOld = DemoBean.getPrivateStaticField();
 5 
 6         Field privateField = DemoBean.class.getDeclaredField("privateStaticField");
 7         privateField.setAccessible(true);
 8 
 9         //该方法跟访问私有的属性是类似的,不同的只是,在调用Field实例的set方法的时候,可以不传实例
10         //当然传实例也是可以进行设置的
11         privateField.set(null, new AtomicInteger());
12 
13         AtomicInteger valNew = DemoBean.getPrivateStaticField();
14         Assert.assertFalse("Two values is equals,but that was not my expected.", valOld.equals(valNew));
15     }

·访问private static final修饰的属性

 1  @Test
 2     public void testGetPrivateStaticFinalField() throws Exception
 3     {
 4         AtomicInteger valOld = DemoBean.getPrivatestaticfinalfield();
 5 
 6         Field targetField = DemoBean.class.getDeclaredField("privateStaticFinalField");
 7         targetField.setAccessible(true);
 8 
 9         //其实访问final的属性,只需要将这个Field的一个标志位(modifiers)修改为非final的
10         Field modifiersField = Field.class.getDeclaredField("modifiers");
11         modifiersField.setAccessible(true);
12         //利用位运算,计算出非final的位,这题步是关键
13         modifiersField.set(targetField, targetField.getModifiers() & ~Modifier.FINAL);
14 
15         targetField.set(null, new AtomicInteger());
16         AtomicInteger valNew = DemoBean.getPrivatestaticfinalfield();
17         Assert.assertFalse("Two values is equals,but that was not my expected.", valOld.equals(valNew));
18     }

关于这一段代码,我稍微解释下吧。

我在研读Field实例的代码的时候,发现,其中存在一个modifiers的属性,这个属性记录着对应属性的修饰符,通过修改final的位,可以进行修改final这个修饰符,来达到强制替换属性实例的目的,这个修改会导致该属性变为非final的。

反射的应用