java技术详解_Java反射技术详解及实例解析
前言
相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!
一、基本反射技术
1.1 根据一个字符串得到一个类
getClass方法
String name = "Huanglinqing";
Class c1 = name.getClass();
System.out.println(c1.getName());
打印结果如下:
Class.forName
比如我们获取java.lang.String的类名
String name = "java.lang.String";
Class c1 = null;
try {
c1 = Class.forName(name);
System.out.println(c1.getName());
} catch (ClassNotFoundException e) {
}
这里也通过捕获异常,因为我们传的这个字符串可能不合法,字符串合法命名是类的命名空间和类的名称组成
打印结果如下:
我们还可以通过c1.getSuperclass()获取到他的父类
Type属性
基本类型都有type属性,可以得到这个基本类型的类型,比如:
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Float.TYPE;
Class c4 = Double.TYPE;
停停停!这些东西有啥子用,如此鸡肋! 别急,一切都是为后续做准备。
二、获取类的成员
当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。
获取类的构造函数
为了便于测试,我们定义一个Test类,Test类如下:(省略get和set方法)
Test类中我们定义是三个私有变量,生成两个公有的含参构造方法和一个私有的含参构造方法以及一个公有的无参构造方法。
public class Test {
private int age;
private String name;
private int testint;
public Test(int age) {
this.age = age;
}
public Test(int age, String name) {
this.age = age;
this.name = name;
}
private Test(String name) {
this.name = name;
}
public Test() {
}
下面我们通过反射获取这些构造方法
获取类的所有构造方法
Test test = new Test();
Class c4 = test.getClass();
Constructor[] constructors ;
constructors = c4.getDeclaredConstructors();
通过getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个,通过getModifiers可以得到构造方法的类型,getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组,所以我们如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:
for (int i = 0; i < constructors.length; i++) {
System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");
Class[] parametertypes = constructors[i].getParameterTypes();
for (int j = 0; j < parametertypes.length; j++) {
System.out.print(parametertypes[j].getName() + " ");
}
System.out.println("");
}
运行结果如下所示:
这样我们就得到了类中所有构造方法和构造方法中的参数,那么我们如何获取特定的构造方法呢?
获取类中特定的构造方法
我们可以通过getConstructors方法获取类中 所有的public类型的构造方法,代码和上面一样就不演示了。
我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。
获取无参构造方法直接不传参数,如下所示:
try {
constructors = c4.getDeclaredConstructor();
System.out.print(Modifier.toString(constructors.getModifiers()) + );
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
这里要进行异常捕获,因为可能不存在对应的构造方法,打印结果如下:
如果我们想获取有两个参数分别为int和String类型的构造方法,代码如下:
Class[] p = {int.class,String.class};
try {
constructors = c4.getDeclaredConstructor(p);
System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");
Class[] parametertypes = constructors.getParameterTypes();
for (int j = 0; j < parametertypes.length; j++) {
System.out.print(parametertypes[j].getName() + " ");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
这里我们同样打印出构造方法的参数:
调用构造方法
从这里开始慢慢到了关键的一步,得到类的实例,我们主要借助于newInstance方法,为了方便演示我们将测试类的两个构造方法打印出来.
public Test(int age, String name) {
this.age = age;
this.name = name;
System.out.println("hello" + name + "i am" + age);
}
private Test(String name) {
this.name = name;
System.out.println("My Name is" +
name);
}
我们先来调用public的方法,如下所示:
Class[] p = {int.class,String.class};
constructors = c4.getDeclaredConstructor(p);
constructors.newInstance(24,"HuangLinqing");
运行打印结果如下:
那么调用私有构造方法呢,和上面一样,只是我们要设置constructors.setAccessible(true);代码如下:
Class[] p = {String.class};
constructors = c4.getDeclaredConstructor(p);
constructors.setAccessible(true);
constructors.newInstance("HuangLinqing");
打印结果如下:
调用类的私有方法
如何调用类中的私有方法呢,我们先在测试类中编写一个测试的私有方法 如下:
private void welcome(String tips){
System.out.println(tips);
}
我们知道如果我们要正常的调用类的方法都是通过类.方法调用,所以我们调用私有方法也需要得到类的实例,而我们上面newInstace已经得到了类的实例,这样就好办了。
Class[] p4 = {String.class};
Method method = c4.getDeclaredMethod("welcome",p4);
method.setAccessible(true);
我们首先通过 getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型
然后通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。
Class[] p4 = {String.class};
Method method = c4.getDeclaredMethod("welcome",p4);
method.setAccessible(true);
Object arg1s[] = {"欢迎关注代码男人技术公众号"};
method.invoke(test,arg1s);
test类的实例当不能new 获取的时候我们也可以通过反射获取,就是上面的newInstance方法。打印结果如下:
获取类的私有字段并修改值
看到这里你可能会说,有了set方法,什么私有不私有,test.set不就可以了,但是这里要注意我们是没有办法得到这个类的实例的,要不然都可以得到实例就没有反射一说了。我们在通过反射得到类的实例之后先获取字段:
Field field = c4.getDeclaredField("name");
field.setAccessible(true);
field.set(o,"代码男人");
o是我们上面通过反射构造方法获取的实例, 打印field.get(o).toString()的值如下:
不过要注意的是我们修改了name的值只对当前的实例对象有效。
Java的基本反射语法就是这样了,欢迎加入技术群一起探讨!
最后反射封装类如下:
package jnidemo.hlq.com.hookdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author Huanglinqing
* @date 2019/4/28
*/
public class Reflex {
/**
* 获取无参构造函数
* @param className
* @return
*/
public static Object createObject(String className) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取无参构造方法
* @param clazz
* @return
*/
public static Object createObject(Class clazz) {
Class[] pareTyple = new Class[]{};
Object[] pareVaules = new Object[]{};
return createObject(clazz, pareTyple, pareVaules);
}
/**
* 获取一个参数的构造函数 已知className
*
* @param className
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object createObject(String className, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取单个参数的构造方法 已知类
*
* @param clazz
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
return createObject(clazz, pareTyples, pareVaules);
}
/**
* 获取多个参数的构造方法 已知className
* @param className
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取构造方法
*
* @param clazz
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
try {
Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
ctor.setAccessible(true);
return ctor.newInstance(pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取多个参数的方法
* @param obj
* @param methodName
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
if (obj == null) {
return null;
}
try {
//调用一个private方法 //在指定类中获取指定的方法
Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
method.setAccessible(true);
return method.invoke(obj, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取一个参数的方法
* @param obj
* @param methodName
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
Class[] pareTyples = {pareTyple};
Object[] pareVaules = {pareVaule};
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
}
/**
* 获取无参方法
* @param obj
* @param methodName
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
}
/**
* 无参静态方法
* @param className
* @param method_name
* @return
*/
public static Object invokeStaticMethod(String className, String method_name) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
}
/**
* 获取一个参数的静态方法
* @param className
* @param method_name
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
}
/**
* 获取多个参数的静态方法
* @param className
* @param method_name
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
try {
Class obj_class = Class.forName(className);
return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 无参静态方法
* @param method_name
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
}
/**
* 一个参数静态方法
* @param clazz
* @param method_name
* @param classType
* @param pareVaule
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
Class[] classTypes = new Class[]{classType};
Object[] pareVaules = new Object[]{pareVaule};
return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
}
/**
* 多个参数的静态方法
* @param clazz
* @param method_name
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
try {
Method method = clazz.getDeclaredMethod(method_name, pareTyples);
method.setAccessible(true);
return method.invoke(null, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getFieldObject(String className, Object obj, String filedName) {
try {
Class obj_class = Class.forName(className);
return getFieldObject(obj_class, obj, filedName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Object getFieldObject(Class clazz, Object obj, String filedName) {
try {
Field field = clazz.getDeclaredField(filedName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
try {
Field field = clazz.getDeclaredField(filedName);
field.setAccessible(true);
field.set(obj, filedVaule);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
try {
Class obj_class = Class.forName(className);
setFieldObject(obj_class, obj, filedName, filedVaule);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Object getStaticFieldObject(String className, String filedName) {
return getFieldObject(className, null, filedName);
}
public static Object getStaticFieldObject(Class clazz, String filedName) {
return getFieldObject(clazz, null, filedName);
}
public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
setFieldObject(classname, null, filedName, filedVaule);
}
public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
setFieldObject(clazz, null, filedName, filedVaule);
}
}
到此这篇关于Java反射技术详解及实例解析的文章就介绍到这了,更多相关Java反射技术示例详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
java技术详解_Java反射技术详解及实例解析相关推荐
- java socket编程心跳_Java Socket编程心跳包创建实例解析
1.什么是心跳包? 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包. 用来判断对方(设备,进程或其它网元)是否正常运行,采用 ...
- java反射机制详解_JAVA反射机制详解_JSP/Java编程_互联网开发技术网_传播最新的编程技术_php361.com...
今天,下午在和朋友聊天的时候,聊起了反射这个话题. 我们就从下面这个段简单的代码开始吧. 这个代码输出什么,想必大部分的读者跟我一样,会很快地知道答案:0 1 2 3 4 5 6 7 8 9.事实也是 ...
- java反射机制详解_Java反射机制详解
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...
- java byte数组操作_Java byte数组操纵方式代码实例解析
字节数组的关键在于它为存储在该部分内存中的每个8位值提供索引(快速),精确的原始访问,并且您可以对这些字节进行操作以控制每个位. 坏处是计算机只将每个条目视为一个独立的8位数 - 这可能是你的程序正在 ...
- java反射源码_java反射技术详解附源码
在学校学习Java时,由于学的不扎实,也没经历过太多实战项目,所以很多重要的知识点瞟一眼就过去了,比如现在要讲的反射,当时直接就忽略掉了,可现在发现很多地方需要反射,不得不重新学习一下,上学欠了太多债 ...
- java反射机制原理详解_java反射机制的详细讲解
一 , 什么是java反射机制? JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象 ...
- java反射模式_Java反射机制详解
对于一般的开发者,很少需要直接使用Java反射机制来完成功能开发,但是反射是很多框架譬如 Spring, Mybatis 实现的核心,反射虽小,能量却很大. 本文主要介绍反射相关的概念以及API的使用 ...
- java反射技术_java反射技术,逆向开发必备技能
相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了, ...
- java 反射技术实例,什么是反射技术?Java中最常用的反射技术实例
什么是反射技术? 动态获取指定类以及类中的内容(成员),并运行其内容.应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象.这时可以根据配置文件的类全名去找对应的字节码文件,并加载进内存, ...
最新文章
- css 实现app图标样式_界面按钮样式丑?不可能!16款css实现炫酷按钮
- Linux下的grep命令
- 实现一个MVVM和promise
- 微软OTech第二次会议(广州站)
- VS Code 1.38 发布!
- 嵌入式Linux启动过程中的问题积累
- 每年的飞鸽传书5月21日都要进一位老师
- 存储技术论坛:最高可用级别的同步复制及方案
- 小学三年级下计算机工作计划,小学三年级第二学期班主任工作计划
- acdsee怎么改图片大小|acdsee怎么用
- 团队任务:第二次冲刺-第三组梦之队
- 计算机潮流分析22节点,第三章电力系统潮流分析与计算第七讲电力网络方程和矩阵及功率方程_255903070...
- vue 和 ssr+nuxt.js 配置环境变量以及pm2进行服务部署
- 03 数据载入、存储及文件格式
- 判断一无符号整数的二进制形式中是否包含偶数个1
- gcc编译工具常用命令以及汇编语言
- 传奇人物、NPC、怪物的头顶封号素材(顶戴花翎功能)添加教程
- 新绝代双骄3终极全攻略6
- prism InvokeCommandAction
- 3. ZCU102 HDMI Demo工程修改【PCIE视频传输】