反射的应用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射的应用相关的知识,希望对你有一定的参考价值。
最近在公司搞一些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的。
以上是关于反射的应用的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?