利用Java反射处理private变量#yyds干货盘点#

古人学问无遗力,少壮工夫老始成。这篇文章主要讲述利用Java反射处理private变量#yyds干货盘点#相关的知识,希望能为你提供帮助。
在java基础中,private是一个访问权限最严格的修饰符。但是在我们工作当中,使用第三方jar包的时候甚至使用JDK里面的工具类的时候,经常会遇到一些private修饰变量,我们想访问甚至修改这个变量的时候就显得比较麻烦。
这个时候我们需要通过Java反射方案来实现我们访问和修改private修饰的变量。
核心API在java.lang.reflect.Field类中有一个java.lang.reflect.AccessibleObject#setAccessible(boolean)方法可以设置反射访问变量的时候跳过权限检查。
这个API不仅可以访问对象变量,也可以访问静态变量。
封装类这个是Groovy写的,对JDK的反射相关API进行了封装,其中有些异常并没有处理。

package com.funtester.utilsimport com.funtester.base.exception.FailExceptionimport java.lang.reflect.Field import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method/** * 私有变量访问工具类,可用于final修饰的变量 */ class PriUtil /*** * 获取私有成员变量的值 * */ static < F> F get(Object instance, String name, Class< F> f) try Field field = instance.getClass().getDeclaredField(name); field.setAccessible(true); // 参数值为true,禁止访问控制检查return (F) field.get(instance); catch (NoSuchFieldException | IllegalAccessException e) FailException.fail("获取$instance.toString()私有变量$name 失败 $e.getMessage()"); /*** * 设置私有成员变量的值 * */ static void set(Object instance, String fileName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException Field field = instance.getClass().getDeclaredField(fileName); field.setAccessible(true); field.set(instance, value); /*** * 访问私有方法 * */ static < F> F call(Object instance, String name, Class< F> r, Class[] parameterTypes, Object[] params) Method method = instance.getClass().getDeclaredMethod(name, parameterTypes); method.setAccessible(true); return (F) method.invoke(instance, params); /** * 获取static变量 * @param c * @param name * @param f * @return */ static < F> F get(Class c, String name, Class< F> f) Field[] fields = c.getDeclaredFields(); try for (Field field : fields) field.setAccessible(true); if (field.getType() == f & & field.getName().equals(name)) return (F) field.get(c); catch (Exception e) FailException.fail("获取$c.name私有变量$name 失败 $e.getMessage()"); /** * 设置static变量 * @param c * @param name * @param f */ static void set(Class c, String name, Object f) Field[] fields = c.getDeclaredFields(); for (Field field : fields) field.setAccessible(true); if (field.getName().equals(name)) field.set(c, f)/** * 调用私有static方法 * @param c * @param name * @param r * @param parameterTypes * @param params * @return */ static < F> Object call(Class c, String name, Class< F> r, Class[] parameterTypes, Object[] params) try Method method = c.getMethod(name, parameterTypes); method.setAccessible(true); return (F) method.invoke(null, params); catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) FailException.fail("执行$c.name私有方法$name 失败,参数 $e.getMessage()")

测试类这里我简单写了一个测试类,一个成员变量,一个类变量。
/** * 反射访问private测试类 */ public class PriBase private String name = "FunTester"; private static String cname = "CFunTester";

测试脚本首先我测试一下非静态变量,测试脚本如下:
import com.funtester.frame.SourceCode import com.funtester.utils.PriUtilclass PriTest extends SourceCodepublic static void main(String[] args) PriBase base = new PriBase() PriUtil.set(base,"name","修改后name") String get = PriUtil.get(base, "name", String.class) output(get) PriBase base1 = new PriBase() String get1 = PriUtil.get(base1, "name", String.class) output(get1)

控制台输出:
INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16 INFO-> main ###### #### ####### ################## ########### ############# ####### ###################### ##### ######## #############################INFO-> main 修改后name INFO-> main FunTesterProcess finished with exit code 0

【利用Java反射处理private变量#yyds干货盘点#】其次我们测试一下静态变量,测试脚本如下:
import com.funtester.frame.SourceCode import com.funtester.utils.PriUtilclass PriTest extends SourceCodepublic static void main(String[] args) PriUtil.set(PriBase.class,"cname","修改后name") String get = PriUtil.get(PriBase.class, "cname", String.class) output(get)

控制台输出:
INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16 INFO-> main ###### #### ####### ################## ########### ############# ####### ###################### ##### ######## #############################INFO-> main 修改后nameProcess finished with exit code 0

完美实现我们的需求,以后再也不用管什么访问权限了,哈哈哈~~~
欢迎关注FunTester,Have Fun ~ Tester !
  • 140道面试题目(UI、Linux、MySQL、API、安全)
  • 分享11份笔试题
  • 分享一份Fiddler学习包
  • 微软Zune闰年BUG分析
  • 绑定手机号性能测试
  • 自动化测试生命周期
  • 软件测试中质量优于数量
  • Web安全检查
  • 基于代码的自动化和无代码自动化
  • Python版Socket.IO接口测试脚本
  • 线程池处理批量接口请求实践
  • Golang fasthttp实践
  • 控制台彩色输出
  • Automa基础功能演示

    推荐阅读