反射 Reflect

  • 反射(Reflect)是在运行时动态访问类与对象的技术

  • 反射是 JDK1.2 版本后的高级特性隶属于 java.lang.reflect

  • 大多数 Java 框架都基于反射实现参数配置、动态注入等特性

    1
    2
    3
    4
    package com.imooc.reflect; 
    public interface MathOperation {
    public float operate(int a, int b);
    }
1
2
3
4
5
6
7
8
9
package com.imooc.reflect;

public class Addition implements MathOperation {
@Override
public float operate(int a, int b) {
System.out.println("执行加法运算");
return a + b;
}
}
1
2
3
4
5
6
7
8
9
package com.imooc.reflect;

public class Subtraction implements MathOperation {
@Override
public float operate(int a, int b) {
System.out.println("执行减法运算");
return a - b;
}
}

测试(普通):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void case1() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入计算类名:");
String op = scanner.next();
System.out.print("请输入a:");
int a = scanner.nextInt();
System.out.print("请输入b:");
int b = scanner.nextInt();
MathOperation mathOperation = null;
if (op.equals("Addition")) {
mathOperation = new Addition();
} else if (op.equals("Subtraction")) {
mathOperation = new Subtraction();
} else if (op.equals("Multiplication")) {
mathOperation = new Multiplication();
} else {
System.out.println("无效的计算类");
return;
}
float result = mathOperation.operate(a, b);
System.out.println(result);
}

测试(反射):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void case2() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入计算类名:");
String op = scanner.next();
System.out.print("请输入a:");
int a = scanner.nextInt();
System.out.print("请输入b:");
int b = scanner.nextInt();
MathOperation mathOperation = null;
try {
mathOperation = (MathOperation) Class.forName("com.imooc.reflect." + op).getDeclaredConstructor().newInstance();
} catch (Exception e) {
System.out.println("无效的计算类");
return;
}
float result = mathOperation.operate(a, b);
System.out.println(result);
}

反射的核心类

1670469858055

Class类

Class是JVM中代表“类和接口”的类。

Class对象具体包含了某个特定类的结构信息。

通过Class对象可获取对应类的构造方法/方法/成员变量

Class核心方法

方法 用途
Class.forName() 静态方法,用于获取指定Class对象
classObj.newlnstance() 通过默认构造方法创建新的对象
classObj.getConstructor() 获得指定的public修饰构造方法Constructor对象
classObj.getMethod() 获取指定的public修饰方法Method对象
classObj.getField() 获取指定的public修饰成员变量Field对象

1670471364992

遇到’newInstance()’ is deprecated (newInstance()已被弃用)的话,解决方法如下:

JAVA9之前用法

1
1 Class.forName("类的全限定名").newInstance();

JAVA9之后用法

1
1 Class.forName("类的全限定名").getDeclaredConstructor().newInstance();

并Add’catch’异常。

1670472634326

1670472678871

Constructor 构造方法类

  • Constructor 类是对 Java 类中的构造方法的抽象
  • Contructor 对象包含了具体类的某个具体构造方法的声明
  • 通过 Constructor 对象调用带参构造方法创建对象
方法 用途
classObj.getConstructor() 获取指定的 public 修饰构造 Constructor 对象
constructorObj.newInstance() 通过对应的构造方法创建对象

实体类 Class 对象 → 实体类构造方法 Constructor 对象 → 实体类对象

1670486878300

1670486907871

Method方法类

  • Method 对象指代某个类中的方法的描述
  • Method 对象使用 classObj.getMethod() 方法获取
  • 通过 Method 对象调用指定对象的对应方法

Method类核心方法

方法 用途
classObj.getMethod() 获取指定的 public 修饰方法 Method 对象
methodObj.invoke() 调用指定对象的对应方法

1670488168440

return this 指的是返回类的当前对象。

1670488323779

invoke( )中要传入两个对象。

invoke(Object obj,Object… args)

Field成员变量

  • Field对应某个具体类中的成员变量的声明
  • Field对象使用classObj.getField()方法获取
  • 通过Field对象可为某对象成员变量赋值/取值

Field类核心方法:

方法 用途
classObj.getField 获取指定public修饰的成员变量对象
fieldObj.set() 为某对象指定成员变量赋值
fieldObj.get() 获取某对象指定成员变量数值

1670489043111

1670490937950

1670491034249

1670491020150

get开头获取方法都是默认获取public修饰的成员变量或方法。

getDeclared系列方法

  • getDeclaredConstructor(s) | Method(s)|Field(s)获取对象
  • getConstructor(s)|Method(s) | Field(s)只能获取public对象
  • 访问非作用域内构造方法、方法、成员变量会抛出异常

    1670575517753

1670576825171getModifiers()方法返回int类型值表示该字段的修饰符

对应表如下:

修饰符 对应的int类型
public 1
private 2
protected 4
static 8
final 16
synchronized 32
volatile 64
transient 128
native 256
interface 512
abstract 1024
strict 2048

反射在项目中的应用案例

1670578067564

1670578132003

1670578153616

1670578167203

1670578174608

1670578188136