JAVA基础篇--反射机制详解

JAVA基础篇--反射机制详解

一、前言:什么是反射

在 Java 开发中,反射(Reflection)是一项强大的技术,可以在运行时动态地访问类的信息、创建对象、调用方法或访问字段。它在框架设计、注解处理、动态代理等方面扮演着重要角色。本文将从基础概念、常见用法、实际应用和注意事项等方面系统地介绍 Java 的反射机制。

二、反射的核心

Java 的反射 API 主要集中在 java.lang.reflect 包中,主要包括以下几个类:

类名作用Class表示正在运行的 Java 类Field表示类的成员变量Method表示类的方法Constructor表示类的构造方法Modifier提供字段或方法的访问修饰符信息

三、常见反射操作示例

1. 获取 Class 对象

// 方式一:通过对象调用 getClass()

Person p = new Person();

Class clazz1 = p.getClass();

// 方式二:通过类名.class

Class clazz2 = Person.class;

// 方式三:通过 Class.forName("全限定类名")

Class clazz3 = Class.forName("com.example.Person");

补充:

Class 对象是 Java 反射 API 的入口点,通过Class可以获取和操作类的几乎所有信息,使得 Java 具有强大的动态能力

Class对象是怎么产生的,这就需要掌握类加载过程,请看这篇博客JVM基础--类加载过程-CSDN博客

2. 获取类信息

System.out.println(clazz.getName()); // 类的全限定名

System.out.println(clazz.getSimpleName()); // 类名

3. 创建对象

Constructor privateCtor = clazz.getDeclaredConstructor();

privateCtor .setAccessible(true); // 解除私有限制

Object obj = privateCtor .newInstance();

getDeclaredConstructor()可以获取任意可见性(包括私有)

4. 通过反射提供的 Constructor 获取对象

Constructor constructor = clazz.getConstructor(String.class, int.class);

Object newObj = constructor.newInstance("李四", 25);

getConstructor(...)只能调用公有的构造器

5. 获取并设置字段

Field field = clazz.getDeclaredField("name");

field.setAccessible(true);//允许访问private字段

field.set(obj, "张三");

System.out.println(field.get(obj)); // 输出:张三

6. 调用方法

//"sayHello"为方法名 String.class是参数的类型

Method method = clazz.getDeclaredMethod("sayHello", String.class);

//关闭java语言访问机制 可以访问private方法,但绕开了 Java 的封装性,引申出来了一个问题

method.setAccessible(true);

//传入的obj是对象实例,如果调用静态方法可以不用传obj(因为静态方法属于类不需要实例即可调用)

//传入的args是方法的参数

method.invoke(obj, args);

四、反射的应用场景

1. 框架设计(如 Spring、Hibernate)

Spring 框架通过反射实现 Bean 的实例化与依赖注入,极大地解耦了代码。

拓展:Spring是怎么通过反射实现的以及Bean的生命周期和循环依赖问题 请看这篇博客

2. 动态代理

JDK 动态代理通过反射构造代理类,在 AOP(面向切面编程)中尤为常见。

拓展:

JAVA中两种动态代理方式,JDK动态代理和CGLIB动态代理 请看这篇博客

AOP(面向切面的编程)

3. 注解处理

通过反射获取类、方法、字段上的注解信息,执行相应逻辑。

五、反射的优缺点

优点:

灵活:在运行时决定行为。

通用:支持编写更通用的框架和工具。

解耦:可减少代码间的耦合性。

缺点:

性能较差:反射操作通常比直接调用慢很多。

安全限制:反射可以访问和修改私有成员,破坏了封装性和安全性。

既然面向对象最重要的特性之一就是面向对象,那么反射破坏了封装性,这是否与封装性相违背?

答案是否定的,因为反射是一种“受控的特权”,Java 并不是默认允许你访问私有成员的,而是通过 AccessibleObject.setAccessible(true) 这个“声明式”方式显式授权的,反射不是为了破坏封装,而是为了解决特殊场景下的通用性需求,比如框架底层开发、测试、序列化等。

可读性差:代码难以维护和理解。

✧ 相关推荐 ✧

Android安卓手机翻墙教程:最好用的安卓VPN推荐
365怎么访问

Android安卓手机翻墙教程:最好用的安卓VPN推荐

📅 07-25 👁️ 2750
女性长期吃醪糟的好处与坏处
365bet博彩官网

女性长期吃醪糟的好处与坏处

📅 07-16 👁️ 1076
卡西:世界杯夺冠都过去14
365怎么访问

卡西:世界杯夺冠都过去14

📅 08-24 👁️ 8170