Java反射

1.反射(Reflection)的定义

指程序在运行期间可以获取到一个对象的全部信息。

2.java中的反射有何特别之处

反射使得Java程序在运行时可以调用反射API获取任何类的内部信息(比如成员变量,成员方法,构造器,接口,父类等),并且可以操作类的实例对象的属性以及方法。

在Java程序中,JWM加载完一个类后,在堆内存中就会产生该类的一个class对象,并且该class对象是唯一的,这个Class对象包含了该类的完整结构信息。

3.获取class类的实例

java 复制代码
// 1 通过类名.class
Class<Student> studentClass1 = Student.class;
System.out.println(studentClass1.hashCode());
// 2 通过Class.forName("类的全类名")  会抛出类未找到异常
Class<?> studentClass2 = Class.forName("com.example.reflect_test.reflect.Student");
System.out.println(studentClass2.hashCode());
// 3 通过对象.getClass获得
Class<? extends Student> studentClass3 = new Student().getClass();
System.out.println(studentClass3.hashCode());
// 4 获取父类实例
Class<? super Student> superclass = studentClass1.getSuperclass();

4.获取该类的属性,方法,接口,父类等

1.获取类名

java 复制代码
String name = studentClass1.getName();              //全类名
String simpleName = studentClass1.getSimpleName();  //单纯类名

2.获取属性(public)

java 复制代码
studentClass1.getField("username");           //指定属性
Field[] fields = studentClass1.getFields();   // 获取所有属性

3.获取属性(public和private)

java 复制代码
Field username = studentClass1.getDeclaredField("username");
Field[] declaredFields = studentClass1.getDeclaredFields();

4.获取方法(public) 包括父类的方法

java 复制代码
// 无参
Method add = studentClass1.getMethod("add");     // 指定方法
Method[] methods = studentClass1.getMethods();   // 所有方法

//有参
Method declaredMethod = studentClass1.getDeclaredMethod("add",String.class,String.class);
declaredMethod.invoke(student,"111","222");

5.获取方法(public和private构造方法) 不包括父类的方法

java 复制代码
Method declaredMethod = studentClass1.getDeclaredMethod("add");
Method[] declaredMethods = studentClass1.getDeclaredMethods();

6.获取类的构造器 (public构造方法)

java 复制代码
Constructor<Student> constructor1 = studentClass1.getConstructor(String.class,String.class);
Constructor<?>[] constructors = studentClass1.getConstructors();

7.获取类的构造器 (public和private构造方法)

java 复制代码
Constructor<Student> declaredConstructor = studentClass1.getDeclaredConstructor(String.class, String.class);

8.获取父类

java 复制代码
Class<? super Student> superclass = studentClass1.getSuperclass();

9.获取接口

java 复制代码
Class<?>[] interfaces = studentClass1.getInterfaces();

5.利用反射创建对象

1.使用newInstance创建(其本质上还是通过无参构造方法创建, 前提是类要有一个无参的public的构造方法)

java 复制代码
Student student = studentClass1.newInstance();

2.利用类的构造器创建对象,无论构造方法是无参还是有参,私有还是公有

java 复制代码
Constructor<Student> declaredConstructor = studentClass1.getDeclaredConstructor(String.class,String.class);  //构造方法参数类型
// 若该构造方法是私有的,如下设置关闭检测
declaredConstructor.setAccessible(true);
Student student = declaredConstructor.newInstance("lisi","wangwu");// 构造方法参数

6.通过反射调用普通方法

  • 无参
java 复制代码
// 1.获取该方法实例
Method declaredMethod = studentClass1.getDeclaredMethod("add");
// 如果该方法是私有的,如下设置关闭检测,提高性能
declaredMethod.setAccessible(true);
// 2.收件利用newInstance或构造器创建对象
Student student = studentClass1.newInstance();
// 3.使用invoke执行该方法(第一个参数是实例对象,第二个是方法传入参数)
declaredMethod.invoke(student,null); 
  • 有参
java 复制代码
// 1.获取该方法实例 (方法名+参数类型)
Method declaredMethod = studentClass1.getDeclaredMethod("add",String.class,String.class);
// 如果该方法是私有的,如下可设置可访问标志
declaredMethod.setAccessible(true);
// 2.利用newInstance或构造器创建对象
Student student = studentClass1.newInstance();
// 2.使用invoke执行该方法(第一个参数是实例对象,第二个是方法传入参数)
declaredMethod.invoke(student,"111","222");

7.通过反射操作属性

java 复制代码
// 1.获取属性实例
Field username = studentClass1.getDeclaredField("username");
// 如果该属性是私有的,如下设置关闭权限检测
username.setAccessible(true);
// 2.获取对象实例
Student student = studentClass1.newInstance();
// 设置属性值
username.get(student);
// 获取属性值
username.set(student,"李四");

8.通过反射获取注解

8.1 读取类上的注解

当作用于类上时,使用类对象.getAnnotation得到注解类型,然后就可以获取变量信息了

java 复制代码
// 自定义一个注解
@Target(ElementType.TYPE) // 该注解用于类上
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String username();
    int age();
}

@MyAnnotation(username = "lisi",age = 20)
class Student1 {
    
}

使用反射获取注解的变量

java 复制代码
// 首先获取类对象
Class<Student1> student1Class = Student1.class;
// 通过 类对象.getAnnotation 获取注解类型
MyAnnotation annotation = student1Class.getAnnotation(MyAnnotation.class);
// 获取变量信息
annotation.username();
annotation.age();

8.2 读取方法上的注解

当作用于方法上时,使用方法类型实例.getAnnotation得到注解类型

java 复制代码
@Target(ElementType.METHOD) // 该注解用于方法上
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String username();
    int age();
}

class Student1 {
    @MyAnnotation(username = "lisi",age = 20)
    public void add() {

    }
}

获取注解的变量

java 复制代码
Class<Student> studentClass = Student.class;
// 得到方法类型
Method add = studentClass.getDeclaredMethod("add");
// 方法类型实例.getAnnotation 获取注解
MyAnnotation annotation = add.getAnnotation(MyAnnotation.class);
// 注解里的变量
annotation.username();
annotation.age();

注解

自定义一个注解

java 复制代码
@Target(ElementType.TYPE)            //指定注解的生命周期(只在属性上生效)
@Retention(RetentionPolicy.RUNTIME)  //指定注解可以应用的目标元素
@interface Order {
    String value() default "";  //这是一个属性,并非方法,注解中比较特殊,加了括号
}

注解的生命周期分类

  • ElementType.TYPE:类、接口、枚举。
  • ElementType.FIELD:字段。
  • ElementType.METHOD:方法。
  • ElementType.PARAMETER:方法参数。
  • ElementType.CONSTRUCTOR:构造函数。
  • ElementType.LOCAL_VARIABLE:局部变量。
  • ElementType.ANNOTATION_TYPE:注解类型。
  • ElementType.PACKAGE:包。

注解可以应用的目标元素

  • RetentionPolicy.SOURCE:注解仅在源代码中保留,编译时会被丢弃。
  • RetentionPolicy.CLASS:注解在编译时被保留,但在运行时不可访问。
  • RetentionPolicy.RUNTIME:注解在运行时保留,可以通过反射机制访问。
相关推荐
benbenAItalk4 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
sunshine22 girl4 小时前
Java学习二 基本语法2, 算术运算符
java·学习
niucloud-admin4 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_962885724 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
滕州市燕猫虎计算机科技工作室个体工商户4 小时前
Java锁
java·开发语言
shehuiyuelaiyuehao6 小时前
1计算机是如何工作的
java·计算机网络
letisgo57 小时前
JAVA 高级进阶07篇《@Transactional失效的8个场景:代理机制到传播行为》
java·面试·transactional·spring事务·aop动态代理
水域安全老周7 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
三8447 小时前
Java 模板注入(FreeMarker) · 02 · 模板引擎与 FreeMarker 语法
java·开发语言·web安全·freemarker
暮雨哀尘8 小时前
Java 基础练习(一):创建类并调用对象
java·开发语言