文章目录
概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
静态编译和动态编译
静态编译:在编译时确定类型,绑定对象
动态编译:运行时确定类型,绑定对象
反射是框架设计的灵魂
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))
Java的反射机制
反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。
反射是允许在运行时检查和操作对象的能力。可以使用反射获取对象的类名、属性、方法和构造函数,并在运行时调用它们
它能够在程序运行的过程中去构造任意一个类对象、并且可以获取任意一个类的成员变量、成员方法、属性,以及调用任意一个对象的方法。通过反射的能力,可以让Java语言支持动态获取程序信息以及动态调用方法的能力。
在Java里面,专门有一个java.lang.reflect用来实现反射相关的类库,包括Construct、Field、Method等类,分别用来获取类的构造方法、成员变量、方法信息。
反射优缺点
优点: 运行期类型的判断,动态加载类,提高代码灵活度。
增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作,提高代码的复用率,比如动态代理,就是用到了反射来实现可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用
缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要
慢很多
反射会涉及到动态类型的解析,所以JVM无法对这些代码进行优化,导致性能要比非反射调用更低。
使用反射以后,代码的可读性会下降
反射可以绕过一些限制访问的属性或者方法,可能会导致破坏了代码本身的抽象性
Java的对象反射什么用
Java的对象反射什么用
1.class,通过反编译,了解到.java文件的本来面目。即为反射
2.Java的反射机制就是增加程序的灵活性,避免将程序写死到代码里。
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性
有助于观察和操纵应用程序的运行时行为。
有助于调试或测试程序,因为我们可以直接访问方法、构造函数和成员字段。
即使事前那个不知道某个方法,我们也可以通过名字调用该方
3.可以通过配置文件来动态配置和加载类,以实现类与类,模块与模块之间的解耦。反射最经典的应用spring框架。
对 Java 反射的理解
在运行状态中,对任意一个类,都能知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法和属性。这种能动态获取信息及动态调用对象方法的功能称为 java语言的反射机制
java反射慢的原因
反射在某些情况下可能会比直接调用方法或访问字段的方式慢,主要是因为以下几个原因:
- 运行时解析:反射涉及到在运行时解析类的结构和调用方法/访问字段。与直接调用方法或访问字段相比,这需要额外的运算开销和时间。
- 安全检查:反射的机制允许绕过正常的访问控制,例如访问私有方法和字段。因此,反射的每一次操作都需要进行安全检查,这会导致一定的性能损耗。
- 自动装箱和拆箱:当使用反射调用方法时,参数的类型通常是Object类型。如果方法参数类型为基本数据类型,那么在反射调用时需要进行自动装箱和拆箱的操作,这会引入额外的性能开销。
- 编译器优化受限:反射的调用方式是在运行时动态确定的,编译器无法进行静态优化。相比之下,直接调用方法或访问字段可以在编译期进行优化,生成更高效的字节码。
尽管使用反射可能会带来一些性能损耗,但在某些情况下,它提供了非常有价值的灵活性和动态性。在需要动态加载类、处理注解、实现依赖注入等场景下,反射是一种强大的工具。在实际应用中,需要权衡使用反射的利弊,并根据具体情况进行选择和优化,以获取最佳的性能和灵活性。
Java反射在性能方面相对较低,但很多框架如Spring使用反射的原因主要有以下几点:
动态扩展和配置:使用反射可以在运行时动态地加载和创建对象,实现灵活的扩展和配置。例如,Spring框架中的依赖注入(DI)就是通过反射来实现的,它可以根据配置文件或注解动态地将依赖注入到对象中,实现对象的解耦和灵活性。
AOP(面向切面编程):AOP是Spring框架的重要特性之一,它通过代理和动态生成子类来实现横切关注点的功能。反射在这个过程中起到了关键作用,可以在运行时动态地创建代理对象,并在方法执行前后进行拦截和增强。
框架灵活性和易用性:使用反射可以获得类的信息,包括字段、方法、注解等,从而实现框架的自动化和灵活性。通过反射,框架可以在运行时动态地获取和调用类的成员,减少了开发人员的工作量,提高了框架的易用性。
虽然反射会引入一定的性能开销,但在很多场景下,这种灵活性和易用性的收益是非常重要的。并且,反射的性能已经在不断地改进和优化中,在一些常见的使用场景下,反射的性能差距可能并不是很明显。
总的来说,框架选择使用反射是为了解决特定的问题和提供更强大的功能,通过权衡性能和灵活性来达到更好的整体设计效果。
相信大家对反射都不陌生,在日常开始的过程中,我们也会经常用到反射来实现某些业务场景,并且很多框架Spring、Mybatis、JDBC等…底层都有靠反射来实现,
反射机制的应用场景有哪些
反射的使用场景还挺多的,比如在动态代理的场景中,使用动态生成的代理类来提升代码的复用性。在Spring框架中,有大量用到反射,比如用反射来实例化Bean对象。
反射 实体和map转换
动态代理
JDBC的class.forName
BeanUtils中属性值的拷贝
rpc框架
orm框架
spring
Java反射在以下场景中常被使用:
- 框架和库:许多框架和库(如Spring、Hibernate等)使用反射来实现依赖注入、配置解析、对象映射等功能。通过反射,可以在运行时动态地加载和操作类,使得框架具有更高的灵活性和扩展性。
- 单元测试:在单元测试中,反射可以帮助我们访问私有方法、私有字段和构造器,以便进行更全面的测试覆盖。
- 序列化和反序列化:当对象需要被序列化到磁盘或通过网络传输时,反射可以帮助我们动态地获取和设置对象的属性值,实现对象的序列化和反序列化。
- 动态配置和扩展:通过读取配置文件或其他外部资源,反射可以根据配置来动态加载和调用具体实现类。这样可以实现应用程序的动态配置和扩展能力。
- ORM(对象关系映射):ORM框架通常使用反射来将数据库中的数据映射到Java对象。通过反射,可以动态地生成SQL语句,将数据库查询结果转换为对象,以及将对象持久化到数据库中。
- 反射工具类:反射还常常被用于编写通用的工具类,例如实现对象克隆、比较对象相等性、获取对象的详细信息等。通过反射,可以获取并操作对象的属性、方法、构造器等信息。
需要注意的是,虽然反射具有很强的灵活性和功能扩展性,但由于其运行时的性能开销较大,过度使用反射可能会影响应用程序的性能。因此,在实际应用中,需要权衡使用反射的利弊,并根据具体情况进行选择和优化。
在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有 用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节 码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大 量使用到了反射机制。
举例:
①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;
②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。
Spring 通过 XML 配置模式装载 Bean 的过程:
- 将程序内所有 XML 或 Properties 配置文件加载入内存中;
2)Java类里面解析 xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
3)使用反射机制,根据这个字符串获得某个类的Class实例;
4)动态配置实例的属性
获取Class对象的三种方式
Class.forName , 类名.Class , 对象.getClass方法
1.Class.forName(className) 所在通过路径-相对路径
2.类名.class
3.this.getClass()。然后将字节码中的方法,变量,构造函数等映射成
相应的 Method、Filed、Constructor 等类,这些类提供了丰富的方法可以被我们所使用。
public class Student {
private int id;
String name;
protected boolean sex;
public float score;
}
public class Get {
//获取反射机制三种方式
public static void main(String[] args) throws ClassNotFoundException {
//方式一(通过建立对象)
Student stu = new Student();
Class classobj1 = stu.getClass();
System.out.println(classobj1.getName());
//方式二(所在通过路径-相对路径)
Class classobj2 = Class.forName(“fanshe.Student”);
System.out.println(classobj2.getName());
//方式三(通过类名)
Class classobj3 = Student.class;
System.out.println(classobj3.getName());
}
}
怎么利用反射获取类中的对象
- 获取 Class 对象
- 通过 Class 对象获取构造方法
- 通过构造方法调用 newInstance()方法创建对象实例
反射的作用:开发过程中,经常会遇到某个类的某个成员变量、方法或属性是私有的,或只对系统应用开放,这里就可以利用 java 的反射机制通过反射来获取所需的私有成员或是方法
- 获取类的 Class 对象实例 Class clz = Class.forName(“com.zhenai.api.Apple”);
- 根 据 Class 对 象 实 例 获 取 Constructor 对 象 Constructor appConstructor =clz.getConstructor();
- 使 用 Constructor 对 象 的 newInstance 方 法 获 取 反 射 类 对 象 Object appleObj =
appConstructor.newInstance(); - 获取方法的 Method 对象 Method setPriceMethod = clz.getMethod(“setPrice”, int.class);
- 利用 invoke 方法调用方法 setPriceMethod.invoke(appleObj, 14);
- 通过 getFields()可以获取 Class 类的属性,但无法获取私有属性,而 getDeclaredFields()可以获取到包括私有属性在内的所有属性。带有 Declared 修饰的方法可以反射到私有的方法,没有 Declared 修饰的只能用来反射公有的方法,其他如 Annotation\Field\Constructor 也是如此
本文探讨了Java反射机制的定义、应用场景、优点和缺点,以及如何获取Class对象和利用反射获取类中的对象。重点分析了反射在性能上的影响以及Spring框架中广泛使用反射的原因。
1235

被折叠的 条评论
为什么被折叠?



