古人学问无遗力,少壮工夫老始成。这篇文章主要讲述利用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基础功能演示
推荐阅读
- #yyds干货盘点#通过正则表达式限制输入框只能数字,且不能以0开头
- #yyds干货盘点# JavaSE系列批量处理数据神器——Java数组与引用
- #私藏项目实操分享#Python爬虫实战,requests+xpath模块,Python实现爬取豆瓣影评
- MySQL之实例重启之前必做得几项工作
- WordPress CSS不起作用
- 迁移到本地主机后,wordpress css链接断开
- WordPress,在更新/删除/创建术语时创建json文件
- WordPress-CPT和ACF插件
- wordpress contact form7与AMP一起使用