Java反射机制(简单易懂)

2022-11-18 14:04:51 浏览数 (1)

文章目录

  • 前言
  • 一、反射机制
  • 二、反射的用途
  • 三、反射相关的类(重要)
    • 3.1 Class类(反射机制的起源 )
    • 3.2 通过反射调用构造方法
    • 3.3 通过反射调用普通方法
    • 3.4 通过反射调用类属性
  • 四、反射的优缺点
  • 总结

前言

博主个人社区:开发与算法学习社区 博主个人主页:Killing Vibe的博客 欢迎大家加入,一起交流学习~~

一、反射机制

反射:在JVM运行时,一切框架的基础。

对于JVM中任何一个类,都能动态获取该类的所有属性和方法。

对于JVM中的任何一个对象,都能动态调用该对象的属性和方法。

动态获取信息以及调用对象机制称为反射机制

二、反射的用途

1、在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。 2、反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。

拓展:

Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

运行时明确该引用到底是啥类型就可以通过反射机制。

三、反射相关的类(重要)

这些类都在java.lang.reflect包下面。

1.Class类: 反射核心类,使用class关键字,包括数组,包括接口编译后生成的class文件就对应一个唯一的class对象,由JVM产生,使用这个class对象就可以获取该类的所有信息。

例如定义如下一个学生类:

代码语言:javascript复制
class Student{
	int age;
	String name;
}

执行 javac Student.java 后 => Student.class

将JVM启动之后,Student类被加载到JVM之后就会产生一个全局唯一的Student.class对象,由JVM产生,就根据这个对象来反射操作Student类

2.Field类:反射调用类中的成员/类属性

3.Method类:反射调用类中的成员/类方法

4.Constructor类:反射调用构造方法

3.1 Class类(反射机制的起源 )

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类 .

无论要通过反射机制干啥事情,首先第一步就是获取该类的class对象(由JVM产生的,全局唯一)

三种方式:

  1. 调用Class.forName(类的全名称) 【包名.类名】
  2. 调用类名称.class 【属性】
  3. 通过该类的任意对象的getClass()

3.2 通过反射调用构造方法

普通的get只能获取public权限的方法或者属性,getDeclared…()可以获取所有权限的方法或属性

示例:

代码语言:javascript复制
   // 1.获取所有public权限的构造方法
        Constructor[] constructors = cls.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("------------------------------");
        // 获取该类所有构造方法
        Constructor[] constructors1 = cls.getDeclaredConstructors();
        for (Constructor constructor : constructors1) {
            System.out.println(constructor);
        }

破坏封装产生对象:

代码语言:javascript复制
// 破坏封装,通过反射破坏private封装,调用私有构造方法
constructor.setAccessible(true);
Student student = constructor.newInstance("Killing Vibe");
System.out.println(student);

3.3 通过反射调用普通方法

invoke方法:

示例:

假设已经获取了Student类的反射对象cls,Student类中有一个test方法

代码语言:javascript复制
 //2.获取要调用方法的Method对象
        Method method1 = cls.getDeclaredMethod("test");
        // test是静态方法,无需产生Student对象
        method1.invoke(null);

        Method method2 = cls.getDeclaredMethod("fun",String.class);
        Student student = new Student("VIBE","男",18);
        method2.invoke(student,"传入的参数");

3.4 通过反射调用类属性

Field.get()方法 : 通过obj对象获取相关属性的值,属性为静态属性,则传入null

Field.set()方法:通过obj对象修改相关属性的值,若为静态对象,则传入null

示例:

假设已经获取了Student类的反射对象cls,Student类中有country,age属性

代码语言:javascript复制
   // 3.获取要拿到的属性Field对象
        Field field = cls.getDeclaredField("country");
        System.out.println(field.get(null));
        Field field1 = cls.getDeclaredField("age");
        Student student = new Student("VIBE","男",18);
        System.out.println(field1.get(student));
        field1.set(student,20);
        System.out.println(field1.get(student));

运行如下:

四、反射的优缺点

优点:

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点

  1. 使用反射会有效率问题。会导致程序效率降低。
  2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

总结

以上就是Java反射机制的原理以及相关类和代码实现,如果有什么疑问或者需要完整代码可以私信博主~~感谢支持

0 人点赞