如何使用反射访问私有字段?含构造注入及测试场景示例
问题1:如何使用反射结合构造注入来访问私有字段?
核心思路是通过反射完成构造注入实例化对象后,再反射突破私有字段的访问限制,具体步骤如下:
- 获取目标类的
Class对象:Kotlin用TargetClass::class.java,Java用TargetClass.class - 获取类的构造方法:如果是私有构造,需调用
constructor.setAccessible(true)开启访问权限;公开构造可直接获取 - 通过构造方法传入参数完成实例化(构造注入核心)
- 获取目标私有字段,调用
field.setAccessible(true)解除访问限制 - 读取字段值用
field.get(实例对象),修改字段值用field.set(实例对象, 新值)
示例代码(Kotlin):
class TargetClass private constructor(private val privateField: String) { // 业务逻辑 } // 反射结合构造注入访问私有字段 fun main() { val clazz = TargetClass::class.java // 获取私有构造方法 val constructor = clazz.getDeclaredConstructor(String::class.java) constructor.isAccessible = true // 构造注入实例化 val instance = constructor.newInstance("初始值") // 获取私有字段 val field = clazz.getDeclaredField("privateField") field.isAccessible = true // 读取字段值 println(field.get(instance)) // 输出:初始值 // 修改字段值 field.set(instance, "修改后的值") println(field.get(instance)) // 输出:修改后的值 }
问题2:测试类中访问AbcViewModel的私有字段networkUtil
针对给定的AbcViewModel类,在测试类中通过反射访问私有字段networkUtil的实现如下:
Kotlin测试类示例
import org.junit.Test import androidx.test.core.app.ApplicationProvider import java.lang.reflect.Field class AbcViewModelTest { @Test fun accessPrivateNetworkUtil() { // 创建ViewModel实例 val app = ApplicationProvider.getApplicationContext<Application>() val viewModel = AbcViewModel(app) // 获取私有字段networkUtil val networkUtilField = AbcViewModel::class.java.getDeclaredField("networkUtil") // 开启字段访问权限 networkUtilField.isAccessible = true // 获取字段对应的实例 val networkUtil = networkUtilField.get(viewModel) as NetworkUtil // 测试断言:验证实例有效性 checkNotNull(networkUtil) } }
Java测试类示例
import org.junit.Test; import androidx.test.core.app.ApplicationProvider; import java.lang.reflect.Field; public class AbcViewModelTest { @Test public void accessPrivateNetworkUtil() throws NoSuchFieldException, IllegalAccessException { Application app = ApplicationProvider.getApplicationContext(); AbcViewModel viewModel = new AbcViewModel(app); Field networkUtilField = AbcViewModel.class.getDeclaredField("networkUtil"); networkUtilField.setAccessible(true); NetworkUtil networkUtil = (NetworkUtil) networkUtilField.get(viewModel); assert networkUtil != null; } }
注意:反射会破坏类的封装性,仅建议在测试场景下使用,生产环境应避免此类操作。
内容的提问来源于stack exchange,提问作者KZoNE
相关产品推荐
相关产品推荐

