
Java基础之反射
发布日期:2021-05-06 23:31:42
浏览次数:5
分类:技术文章
本文共 5231 字,大约阅读时间需要 17 分钟。
一、概述
在运行状态中,对于任何一个类都能知道这个类中的所有属性、方法;对于任意一个对象,都能调用它的属性、方法;这种动态获取信息以及动态调用对象方法的功能,称之为反射。
二、通过反射查看类信息
1.获取Class对象
类被加载后,会生成一个对应的Class对象。通过Class对象,就能访问到JVM中的这个类。获取Class对象,概括分为3中方式:
//通过静态方法forName实现 class = Class.forName(com.xxx.xxx.Person); //通过class属性 class = Person.class; //通过对象的getClass方法 Person person = new Person(); Class class = person.getClass();
2.获取Class对象的属性、方法、构造函数
a.获取class对象的成员变量
Field[] allFields = class1.getDeclaredFields();//获取class对象所有属性 Field ageField = class1.getDeclaredField("age");//获取指定属性 Field[] PublicFields = class1.getFields();//获取public属性 Field desField = class1.getField("age");//获取指定的public属性
b.获取class对象方法
Method[] methods = class1.getDeclaredMethods();//获取所有方法 Method declaredMethod = class1.getDeclaredMethod("info", String.class);//返回带指定形参列表的方法 Method[] allMethods = class1.getMethods();//返回所有public方法 Method method = class1.getMethod("info", String.class);//返回带指定形参列表的pulic方法
c.获取class对象构造函数
Constructor [] allConstructors = class1.getDeclaredConstructors();//返回所有构造方法 Constructor constructor = class1.getDeclaredConstructor(String.class);//获取指定声明的构造方法 Constructor [] publicConstructors = class1.getConstructors();//返回所有public构造方法 Constructor publiconstructor = class1.getConstructor(String.class);//返回指定的public构造方法
d.其他方法
Annotation[] annotations = (Annotation[]) class1.getAnnotations();//获取class对象所有注解 Annotation annotation = (Annotation) class1.getAnnotation(Deprecated.class);//获取指定注解 Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类type Type[] genericInterfaces = class1.getGenericInterfaces();//获取class对象所有接口的type结婚
3.获取class对象的信息
boolean primitive = class1.isPrimitive();//是否是基础类型 boolean array = class1.isArray();//是否是集合类 boolean annotation = class1.isAnnotation();//是否是注解类 boolean anInterface = class1.isInterface();//是否是接口类 boolean anEnum = class1.isEnum();//是否是枚举类 boolean anonymousClass = class1.isAnonymousClass();//是否是匿名内部类 boolean annotationPresent = class1.isAnnotationPresent(Deprecated.class);//是否被某个注解类修饰 String name = class1.getName();//获取class的name,包括包路径 Package aPackage = class1.getPackage();//获取包信息 String simpleName = class1.getSimpleName();//获取class类名 int modifiers = class1.getModifiers();//获取访问权限 Class [] declaredClasses = class1.getDeclaredClasses();//内部类 Class declaringClass = class1.getDeclaringClass();//外部类
三、通过反射生成并操作对象
1.生成类的实例对象
//调用newInstance()生成 Object obj = class1.newInstance(); //通过构造方法在调用newInstance()生成 Constructor constructor = class1.getDeclaredConstructor(String.class); Object obj = constructor.newInstance("hello");
2.调用类的方法
Object obj = class1.newInstance();//生成新的对象 Method method = class1.getDeclaredMethod("setAge", int.class);//获取与该方法对应的Method对象 method.invoke(obj,11);//调用指定函数并传参
通过Method的invoke方法来调用对应方法时,程序必须要有调用该方法的权限。如果需要调用某个对象的private方法,可先调用setAcccessible(boolean flag);true代表Method在使用时取消访问权限检查,false表示启用访问权限检查。
3.访问成员变量值
Object obj = class1.newInstance();//生成新的对象 Field field = class1.getField("age");//获取age变量 field.setInt(obj,10);//将age设置10 field.getInt(obj);//取出age
四、反射结合泛型
1.泛型和Class类
在反射中使用泛型,可以避免反射生成的对象需要强制类型转换。
//工厂类public class ObjectFactory { public staticT getInstance(Class cls){ try { return cls.newInstance(); } catch (InstantiationException |IllegalAccessException e) { e.printStackTrace(); return null; } }}
此时传入String.class,T便代表String,返回的对象是String类型,避免了强制类型转换
String instance = ObjectFactory.getInstance(String.class);
2.使用反射获取泛型信息
通过类对应的Class对象,可以获取到所有的Field,并获得Field类型:
//获取field对象f的类型Class a = f.getType();
如果Field类型是有泛型限制的类型,如Map<String,Integer>,就不灵了。只能先获取Field类型,再把type对象强制转换为ParameterizedType(代表被参数化的类型,即增加了泛型限制的类型)对象,ParameterizedType提供了getRawType()(返回没有泛型信息的原始类型)和getActualTypeArguments()(返回泛型参数的类型)
public class GenericTest { private Mapscore; public static void main(String []args) throws Exception { Class clazz = GenericTest.class; Field f = clazz.getDeclaredField("score"); //直接使用getType取出Field类型,只对普通类型的Field有效 Class a = f.getType(); System.out.println("score类型为"+a); //获取Field实例f的泛型类型 Type gType = f.getGenericType(); //如果gType类型时ParameterizedType if (gType instanceof ParameterizedType){ ParameterizedType pType = (ParameterizedType) gType; //获取原始类型 Type rType = pType.getRawType(); System.out.println("原始类型时"+rType); //获取泛型类型的泛型参数 Type[] tArgs = pType.getActualTypeArguments(); for (int i = 0; i < tArgs.length; i++) { System.out.println(i+"个泛型类型是:"+tArgs[i]); } }else { System.out.println("获取泛型类型出错"); } }}
以上输出结果:
score类型为interface java.util.Map 原始类型时interface java.util.Map 0个泛型类型是:class java.lang.String 1个泛型类型是:class java.lang.Integer使用场景
1.逆向编码,如反编译
2.与注解相结合的框架,如Retrofit 3.单纯的反射机制应用框架,如EventBus 4.动态生成类框架,如Gson发表评论
最新留言
表示我来过!
[***.240.166.169]2025年03月14日 17时12分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
ThinkCMF报错未定义变量vo
2019-03-04
微信公众号开发之素材管理
2019-03-04
修改dynamic web module的版本大小
2019-03-04
IDEA 成功在tomcat上部署项目
2019-03-04
Node.js response 页面中文乱码
2019-03-04
谷歌浏览器 禁用JavaScript
2019-03-04
gitee 修改个人域名 个人空间地址 URL
2019-03-04
C++11中bind的使用错误
2019-03-04
Android中CMake的使用之一初步总结
2019-03-04
一起学智能合约之四表达式和控制结构
2019-03-04
futex同步机制分析之三内核实现
2019-03-04
多线程的伪共享
2019-03-04
flink分析使用之五工作图的生成和分发
2019-03-04
基于OpenCV的路面质量检测
2019-03-04
Spring Cloud系列_11 Feign负载均衡、请求传参
2019-03-04
leetcode 543. Diameter of Binary Tree
2019-03-04
VSLAM系列原创01讲 | 深入理解ORB关键点提取:原理+代码
2019-03-04
卡尔曼滤波器的特殊案例
2019-03-04
基于Opencv的图像单应性转换实战
2019-03-04