java反射
1、Class对象
理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息。Class对象就是用来创建所有“常规”对象的,Java使用Class对象来执行RTTI,即使你正在执行的是类似类型转换这样的操作。
每个类都会产生一个对应的Class对象,也就是保存在.class文件。所有类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类。Class对象仅在需要的时候才会加载,static初始化是在类加载时进行的。
类加载器首先会检查这个类的Class对象是否已被加载过,如果尚未加载,默认的类加载器就会根据类名查找对应的.class文件。
想在运行时使用类型信息,必须获取对象(比如类Base对象)的Class对象的引用,使用功能Class.forName(“Base”)可以实现该目的,或者使用base.class。注意,有一点很有趣,使用功能”.class”来创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象。为了使用类而做的准备工作一般有以下3个步骤:
- 加载:由类加载器完成,找到对应的字节码,创建一个Class对象
- 链接:验证类中的字节码,为静态域分配空间
- 初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块
@PostConstruct public void init() throws NoSuchFieldException { Field[] fields = this.getClass().getDeclaredFields(); Arrays.asList(fields) .forEach( field -> { Method[] methods = field.getType().getMethods(); Map<String, Method> methodMap = new ConcurrentHashMap<>(); Arrays.asList(methods) .forEach( method -> { methodMap.put(method.getName(), method); }); try { field.setAccessible(true); CLASS_METHODS.put(field.get(this), methodMap); } catch (IllegalAccessException e) { e.printStackTrace(); } }); }
上面的代码是填充一个map,map的每一个元素是这个类的成员变量,和这个变量的方法集合。
反射主要使用Class这个类的方法
补充资料:
反射性能很差是没错的,但是现在没有几个框架不用反射的。
关键是如何用,理想的情况是应用启动时一次反射,注入,之后不再扫描。如spring的实现。
后果是应用启动较慢,但一旦启动就健步如飞了。
二是需要动态加载的场景,这时要合理地使用缓存,把通过反射查询到的结果缓存起来。结果是第一次访问较慢,以后便和没有用反射一样了。
反射带来了代码的灵活性,减少代码量,减少重复工作,因为代码少了,所以减少了BUG.
反射是否真的会让你的程序性能降低?
1.反射大概比直接调用慢50~100倍,但是需要你在执行100万遍的时候才会有所感觉
2.判断一个函数的性能,你需要把这个函数执行100万遍甚至1000万遍
3.如果你只是偶尔调用一下反射,请忘记反射带来的性能影响
4.如果你需要大量调用反射,请考虑缓存。
5.你的编程的思想才是限制你程序性能的最主要的因素
————————————————
版权声明:本文为CSDN博主「扶公瑾以苏」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36470686/article/details/85015753
)反射的缺点
性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
使用反射会模糊程序内部逻辑:程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
一个优缺点详述的博客
https://blog.nowcoder.net/n/65f9c91727f44476bb0cb1770acb1d30