java反射

一、定义:

Java 的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。

通常情况下,我们想调用一个类内部的属性或方法,需要先实例化这个类,然后通过对象去调用类内部的属性和方法;通过 Java 的反射机制,我们就可以在程序的运行状态中,动态获取类的信息,注入类内部的属性和方法,完成对象的实例化等操作。

图中解释了两个问题:

1、程序运行状态中指的是什么时刻:Hello.java 源代码文件经过编译得到 Hello.class 字节码文件,想要运行这个程序,就要通过 JVM 的 ClassLoader (类加载器)加载 Hello.class,然后 JVM 来运行 Hello.class,程序的运行期间指的就是此刻;

2、什么是反射,它有哪些功能:在程序运行期间,可以动态获得 Hello 类中的属性和方法、动态完成 Hello 类的对象实例化等操作,这个功能就称为反射。

二、优点

框架:反射、泛型、注解

1、扩展性和灵活性:通过反射机制,可以实现动态加载类、调用方法、访问字段等操作,从而使程序具有更强的扩展性和灵活性。这在开发框架、插件系统或通用库时非常有用。

2、框架设计:许多 Java 框架(如Spring框架)都广泛使用了反射机制,通过反射可以实现依赖注入、AOP编程等功能。

3、框架源码阅读:许多开源框架和库中广泛使用了反射,学习反射可以帮助更好地理解和阅读这些框架的源码。

4、编写通用工具类:通过反射可以编写一些通用的工具类,比如序列化/反序列化工具、注解处理器、配置文件解析器等。虽然反射机制有很多优点,但也需要注意反射可能带来的性能开销和安全隐患。因此,在使用反射时需要谨慎考虑,并避免滥用。总的来说,学习反射机制有助于提高 Java 程序员的编程技能和应用开发能力。

三、反射的缺点

尽管反射机制提供了很大的灵活性和扩展性,但也存在一些缺点和不足之处,包括:

1、性能开销:使用反射会导致性能开销较大,因为在运行时需要动态地解析类结构、查找方法或字段等,比直接调用方法要慢很多。这对性能要求高的应用可能不太适用。

2、编译时检查失效:由于反射是在运行时进行的,因此编译器无法对反射代码进行类型检查,容易引入类型错误,造成运行时异常。

3、安全性问题:通过反射可以访问和修改类的私有字段和方法,这可能会绕过类的封装性,造成安全隐患,特别是在安全敏感的应用中需要格外小心。4、可读性和维护性差:使用反射的代码通常比直接调用更难理解和维护,因为它隐藏了类的结构和行为,使得代码更加晦涩难懂。

5、性能优化困难:由于反射是在运行时动态进行的,因此很难进行静态分析和优化,使得程序的性能优化变得更加困难。

6、不利于代码重构:使用反射的代码通常依赖于类的具体实现细节,一旦类结构发生变化,可能导致反射代码出错,不利于代码的重构和演化。

综上所述,虽然反射机制为 Java 程序员提供了很多便利,但在实际应用中需要谨慎使用,权衡利弊。在性能要求高、安全性要求严格或代码可维护性重要的情况下,建议尽量避免过度依赖反射机制,寻找其他更合适的解决方案。

类比学习一下面向对象抽象过程

结构里面包含哪些东西呢: Field、Constructor、Method,同样这些众多的属性、构造函数、方法也有对应的类类型表示他们。

Java.lang.Class;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Constructor;

对于类型的学习我们可以参考做月饼的模子,什么样模子就可以做出什么大小,图案的月饼。对于Java里面的int类型是四个字节,那么这个模子就是一个只能存放四个字节的模子,用这个模子做出来的就是int类型。

同理Class、Field、Method、Constructor就分别是类、属性、方法、构造函数的模子。

通过Class可以获得类的所有属性Field[]、方法Method[]、构造方法Constructor[]信息。

通过Field可以获得属性的名字、类型、修饰符

通过Method可以获得方法的名字、参数、返回值。

五、反射常用类

学习反射就需要了解反射相关的一些类,下面我们来看一下如下这几个类:

1、Class:Class 类的实例表示正在运行的 Java 应用程序中的类和接口;

2、Constructor:关于类的单个构造方法的信息以及对它的权限访问;

3、Field:Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限;

4、Method:Method 提供关于类或接口上单独某个方法的信息。

通俗理解要做反射首先获得字节码对象(描述对应的信息),拿到对象之后才能拿到constructormethodfield信息所以第一步首先获得字节对象字节码对象有三种获取方式

//a.通过类路径获得 Class.forName(类路径)
Class a  = Class.forName("com.situ.day23.Student);
//b.类型.class
Class b = Student.class;
//c. 对象.getClass()
Student student = new Student();
Class c  = student.getClass();

public void testConstructor() {
   Class clazz = Student.class;
   Constructor[] constructors = clazz.getDeclaredConstructors();
   for (Constructor constructor : constructors) {
     System.out.println(constructor);
     System.out.println(constructor.getName());//构造方法的名字
     System.out.println(constructor.getModifiers());//修饰符
   }
}

public  com.situ.day15.Student()
com.situ.day15.Student
1
private  com.situ.day15.Student(java.lang.String)
com.situ.day15.Student
2

@Test
public void testConstructor2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    Class clazz = Student.class;
    //private Student(Integer id, String name, Integer age, String gender)
    Constructor constructor = clazz.getDeclaredConstructor(Integer.class, String.class, Integer.class, String.class);
    //在反射面前,私有的都可以访问
    constructor.setAccessible(true);
    //Student student = new Student(1, "zhansgan", 23, "男");
    Student student = (Student) constructor.newInstance(1, "zhangsan", 23, "男");
    System.out.println(student);
}
Student{id=1, name='zhangsan', age=23, gender='男'}

public void testMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
   //Student student = new Student();
   //student.setName("lisi");
   
   Class clazz = Class.forName("com.situ.day15.Student");
   //得到无参构造方法
   Constructor constructor = clazz.getConstructor();
   //调用newInstance实例化对象
   Student student = (Student) constructor.newInstance();
   //student.setName("lisi");
   Method method = clazz.getMethod("setName", String.class);
   method.invoke(student, "lisi");
   System.out.println(student);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值