从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

  • JavaSenior

    • 反射

      • 什么是反射
      • 反射的原理
      • Class 介绍
        • 获取 Class 对象的方式
        • Class 类的常用方法
        • 实践 Field 成员变量
        • 实践 Constructor 构造方法
        • 实践 Methods
        • 实践 类名和包名
        • 实践 小型 Spring
        • 其他注意事项
      • 反射小结
    • 注解

    • 集合类

    • 线程

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java
  • JavaSenior
  • 反射
2022-12-30
目录

Class 介绍

# Class 介绍

Class 是反射的基础

# 获取 Class 对象的方式

要用反射来操作某个类的变量或方法,首先要获取该类的 Class 对象。

一共 3 种方式,对应 3 个阶段.

  • Class.forName("全类名") :将字节码文件加载进内存,返回 Class 对象。因为在第一阶段,只有字节码文件,需要手动加载进内存。多用于配置文件,将类名定义在配置文件中。读取文件,加载类。(全类名:包名.类名)
  • 类名.class :通过类名的属性 class 获取。 在 Class 类对象阶段,在第二阶段,已经在内存了,直接获取就可以了。多用于参数的传递
  • 对象.getClass() :getClass()方法在 Object 类中定义着,所有类都继承了 Object。在 Runtime 运行时阶段,第三阶段。多用于对象的获取字节码的方式,即已经有了对象了,直接获取。

以下代码的结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的 Class 对象都是同一个。不同的字节码文件(也就是不同的类),则当然会不同,也就不会相等。

/**
 获取Class对象的方式:
  1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
  2. 类名.class:通过类名的属性class获取
  3. 对象.getClass():getClass()方法在Object类中定义着。
  */

package com.peterjxl.reflect;

public class ReflectDemo1GetClassObject{
  public static void main(String[] args) throws Exception {
    Person person = new Person();

    //1.Class.forName("全类名") 静态方法
    Class class1 = Class.forName("com.peterjxl.reflect.Person");

    //2.类名.class
    Class class2 = Person.class;

    //3.对象.getClass()
    Class class3 = person.getClass();

    System.out.println("class1: "+ class1); //class com.peterjxl.reflect.Person
    System.out.println("class2: "+ class2); //class com.peterjxl.reflect.Person
    System.out.println("class3: "+ class3); //class com.peterjxl.reflect.Person

    System.out.println("class1 == class2: " + (class1 == class2));  //true
    System.out.println("class2 == class3: " + (class2 == class3));  //true

    Class classStu = Student.class;
    System.out.println("classStu == class1: " + (classStu == class1));  //false
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.peterjxl.reflect;

public class Person {

}
1
2
3
4
5
package com.peterjxl.reflect;

public class Student {

}
1
2
3
4
5

目录结构:

当前路径:D:\Projects\LearnJava\02.JavaSenior\01.Reflect
目录结构:
01.Reflect
└── com
    └── peterjxl
        └── reflect
            ├── Person.java
            ├── ReflectDemo1GetClassObject.java
            └── Student.java
1
2
3
4
5
6
7
8
9

编译和运行:

> javac -d ./bin ./com/peterjxl/reflect/*.java -encoding utf8

cd ./bin
> java -cp . com.peterjxl.reflect.ReflectDemo1GetClassObject
class1: class com.peterjxl.reflect.Person
class2: class com.peterjxl.reflect.Person
class3: class com.peterjxl.reflect.Person
class1 == class2: true
class2 == class3: true
classStu == class1: false
1
2
3
4
5
6
7
8
9
10

注意:因为有可能有必检异常,因此必须对异常进行处理(我这里在 main 方法里抛出了),不然会报错:

错误: 未报告的异常错误ClassNotFoundException; 必须对其进行捕获或声明以便抛出
1

# Class 类的常用方法

查看 Class 类的文档,该类里面大部分都是 get 开头的方法。

  • 获取成员变量们

    • Field[] getFields():获取所有 public 修饰的成员变量,包括父类
    • Field getField(String name): 获取指定名称的 public 修饰的成员变量(不包括父类)
    • Field[] getDeclaredFields() : 获取所有的成员变量,不考虑修饰符。经简单测试,Filed 数组里的顺序和类里面成员定义的顺序是一致的。
    • Field getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符(不包括父类)
  • 获取构造方法们

    • Constructor<?>[] getConstructors():获取所有 public 修饰的构造方法
    • Constructor<T> getConstructor(类<?>... parameterTypes):获取指定的、public 修饰的构造方法
    • Constructor<T> getDeclaredConstructor(类<?>... parameterTypes):获取所有的的构造方法,不考虑修饰符
    • Constructor<?>[] getDeclaredConstructors() 获取指定的构造方法,不考虑修饰符
  • 获取成员方法们:

    • Method[] getMethods():获取所有 public 修饰的成员方法
    • Method getMethod(String name, 类<?>... parameterTypes) 获取指定的、public 修饰的成员方法
    • Method[] getDeclaredMethods():获取所有成员方法
    • Method getDeclaredMethod(String name, 类<?>... parameterTypes) 获取指定的的成员方法,不考虑修饰符
  • 获取全类名和包名

    • String getName()
    • Package getPackage()
    • Class getSuperclass() : 获取父类的 Class, Object 的父类是 null
    • Class[] getInterfaces():查询到实现的接口类型。只返回当前类直接实现的接口类型,并不包括其父类实现的接口类型。如果没有实现任何 interface,返回空数组。

如果父类的属性用 protected 修饰,利用反射是无法获取到的。

protected 修饰符的作用范围:只允许 同一个包下 或者 子类 访问,可以继承到子类。

getFields() 只能获取到本类的 public属性的变量值;

getDeclaredFields() 只能获取到本类的所有属性,不包括父类的;

所以,无论如何都获取不到父类的 protected 属性修饰的变量,但是它的的确确存在于子类中。

# 实践 Field 成员变量

Field 对象常用方法:

  • 设置值:void set(Object obj, Object value)
  • 获取值:get(Object obj)
  • 忽略访问权限修饰符的安全检查:setAccessible(true) ,也叫暴力反射
  • getName():返回字段名称,例如,"name";
  • getType():返回字段类型,也是一个 Class 实例,例如,String.class;
  • getModifiers():返回字段的修饰符,它是一个 int,不同的 bit 表示不同的含义。

以 String 类的 value 字段为例,它的定义是:

public final class String {
    private final byte[] value;
}
1
2
3

我们用反射获取该字段的信息,代码如下:

Field f = String.class.getDeclaredField("value");
f.getName(); // "value"
f.getType(); // class [B 表示byte[]类型
int m = f.getModifiers();
Modifier.isFinal(m); // true
Modifier.isPublic(m); // false
Modifier.isProtected(m); // false
Modifier.isPrivate(m); // true
Modifier.isStatic(m); // false
1
2
3
4
5
6
7
8
9

我们实践下,定义一个 Person 类先:

package com.peterjxl.reflect;

public class Person {

    public String pubName;
    protected String proName;
    String defName;
    private String priName;

    public Person(){

    }

    public Person(String pubName){
        this.pubName = pubName;
    }

    public void eat(){
        System.out.println("Person eating.....");
    }

    @Override
    public String toString(){
        return "pubName: " + this.pubName;
    }

    public void setPriName(String priName) {
        this.priName = priName;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
  演示Class获取成员变量
  1.Field[] getFields():获取所有public修饰的成员变量
  2.Field getField(String name):  获取指定名称的 public修饰的成员变量
  3.Field[] getDeclaredFields() : 获取所有的成员变量,不考虑修饰符
  4.Field getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符
 */
package com.peterjxl.reflect;

import java.lang.reflect.Field;

public class ReflectDemo2GetMember{
  public static void main(String[] args) throws Exception {
    //0.获取Person的Class对象
    Class personClass = Person.class;

    //1.getFields():获取所有public修饰的成员变量
    Field[] fields = personClass.getFields();
    for (Field field : fields) {
      System.out.println(field);  //public java.lang.String com.peterjxl.reflect.Person.pubName
    }





    //2.getField(String name):  获取指定名称的 public修饰的成员变量
    Field pubNameField = personClass.getField("pubName");
    System.out.println("pubNameField: " + pubNameField);  //pubNameField: public java.lang.String com.peterjxl.reflect.Person.pubName
    Person zhangsan = new Person("zhangsan");

    //获取成员变量 pubName 的值
    Object value = pubNameField.get(zhangsan);
    System.out.println("zhangsan value = " + value);  //zhangsan value = zhangsan
    // 设置成员变量 pubName 的值
    pubNameField.set(zhangsan, "lisi");
    System.out.println("After set zhangsan value: " + zhangsan);  //After set zhangsan value: pubName: lisi





    //3.getDeclaredFields() : 获取所有的成员变量,不考虑修饰符
    Field[] declarFields = personClass.getDeclaredFields();
    for (Field declarField : declarFields) {
      System.out.println(declarField);
    }
    /*
      public java.lang.String com.peterjxl.reflect.Person.pubName
      protected java.lang.String com.peterjxl.reflect.Person.proName
      java.lang.String com.peterjxl.reflect.Person.defName
      private java.lang.String com.peterjxl.reflect.Person.priName
     */



    //4.getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符
    Person wangwu = new Person();
    wangwu.setPriName("wangwu");
    Field priNameField = personClass.getDeclaredField("priName");
    System.out.println("priNameField: " + priNameField);  // priNameField: private java.lang.String com.peterjxl.reflect.Person.priName

    //忽略访问权限修饰符的安全检查  因为priName是Person的私有变量,默认是不允许类外部访问和设置,但可以通过设置强制获取。
    priNameField.setAccessible(true);
    System.out.println(priNameField.get(wangwu)); //wangwu
    priNameField.set(wangwu, "wangwu2");
    System.out.println("After set wangwu priName:" + priNameField.get(wangwu)); //After set wangwu priName:wangwu2
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

输出举例:

public java.lang.String com.peterjxl.reflect.Person.pubName

pubNameField: public java.lang.String com.peterjxl.reflect.Person.pubName

zhangsan value = zhangsan
After set zhangsan value: pubName: lisi

public java.lang.String com.peterjxl.reflect.Person.pubName
protected java.lang.String com.peterjxl.reflect.Person.proName
java.lang.String com.peterjxl.reflect.Person.defName
private java.lang.String com.peterjxl.reflect.Person.priName

priNameField: private java.lang.String com.peterjxl.reflect.Person.priName
wangwu
After set wangwu priName:wangwu2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果没有忽略访问权限修饰符的安全检查,会抛出异常 IllegalAccessException:

//Field getDeclaredField(String name)
Person wangwu = new Person("wangwu");
Field priNameField = personClass.getDeclaredField("priName");
System.out.println(priNameField.get(wangwu));
1
2
3
4
Exception in thread "main" java.lang.IllegalAccessException: Class com.peterjxl.reflect.ReflectDemo2GetMember can not access a member of class com.peterjxl.reflect.Person with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Field.get(Field.java:390)
	at com.peterjxl.reflect.ReflectDemo2GetMember.main(ReflectDemo2GetMember.java:64)
1
2
3
4
5
6

# 实践 Constructor 构造方法

由于构造方法的方法名全部一样,所以区分方法要看参数列表。

我们可以用它来创建对象:

  • T newInstance(Object... initargs)
  • 如果使用空参数构造方法创建对象,操作可以简化:Class 对象的 newInstance 方法
  • 如果要调用私有的构造器,也需要使用暴力反射 setAccessible(true);
/**
 获取构造方法们
  1. Constructor<?>[] getConstructors() 获取所有public修饰的构造方法
  2. Constructor<T> getConstructor(类<?>... parameterTypes) 获取指定的、public修饰的构造方法
  3. Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 获取所有的的构造方法,不考虑修饰符
  4. Constructor<?>[] getDeclaredConstructors() 获取指定的构造方法,不考虑修饰符
  3和4比较少见,这里不演示
*/

package com.peterjxl.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class ReflectDemo3GetConstructor {
  public static void main(String[] args) throws Exception {
    // 0.获取Person的Class对象
    Class personClass = Person.class;

    // 1. Constructor<?>[] getConstructors() 获取所有public修饰的构造方法
    Constructor[] constructors = personClass.getConstructors();
    for (Constructor constructor : constructors) {
      System.out.println(constructor);
    }

    // 2. 获取指定的、public修饰的构造方法
    Constructor constructor = personClass.getConstructor(String.class);
    Constructor constructor2 = personClass.getConstructor();  //获取空参构造函数
    System.out.println("constructor: " + constructor);

    // 创建对象newInstance
    Object person = constructor.newInstance("爱莉希雅");
    System.out.println(person);

    // 调用Class对象的newInstance方法,简化对象的创建
    Object person2 = personClass.newInstance();
    System.out.println(person2);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

输出:

public com.peterjxl.reflect.Person()
public com.peterjxl.reflect.Person(java.lang.String)

constructor: public com.peterjxl.reflect.Person(java.lang.String)   

pubName: 爱莉希雅

pubName: null
1
2
3
4
5
6
7
8

# 实践 Methods

Method:方法对象

  • 获取方法:需要方法名,参数列表
  • 执行方法:Object invoke(Object obj, Object... args),args 是方法的参数列表。如果是静态方法,obj 传入 null 即可。
  • 可以使用暴力反射 setAccessible(true);

其他常用:

  • getName():返回方法名称,例如:"getScore";
  • getReturnType():返回方法返回值类型,也是一个 Class 实例,例如:String.class;
  • getParameterTypes():返回方法的参数类型,是一个 Class 数组,例如:{String.class, int.class};
  • getModifiers():返回方法的修饰符,它是一个 int,不同的 bit 表示不同的含义。
/**
 获取成员方法们:
  1.Method[] getMethods() 获取所有public修饰的成员方法
  2.Method getMethod(String name, 类<?>... parameterTypes) 获取指定的、public修饰的成员方法
  3.Method[] getDeclaredMethods() 获取所有成员方法
  4.Method getDeclaredMethod(String name, 类<?>... parameterTypes) 获取指定的的成员方法,不考虑修饰符
*/


package com.peterjxl.reflect;
import java.lang.reflect.Method;

public class ReflectDemo4GetMethods {
  public static void main(String[] args) throws Exception{
    //0.获取Person的Class对象
    Class personClass = Person.class;

    // 1. getMethods() 获取所有public修饰的成员方法
    Method[] methods = personClass.getMethods();
    for (Method method : methods) {
      System.out.println("method.getName(): " + method.getName());
      System.out.println(method);
    }

    //  2.getMethod(String name, ... parameterTypes) 获取指定的、public修饰的成员方法
    Person person = new Person();
    Method eat_method = personClass.getMethod("eat", String.class);
    // 执行该方法
    eat_method.invoke(person, "fries");
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

编译和运行:

method.getName(): toString
public java.lang.String com.peterjxl.reflect.Person.toString()  
method.getName(): setPriName
public void com.peterjxl.reflect.Person.setPriName(java.lang.String)method.getName(): eat
public void com.peterjxl.reflect.Person.eat()
method.getName(): eat
public void com.peterjxl.reflect.Person.eat(java.lang.String)   
method.getName(): wait
public final void java.lang.Object.wait() throws java.lang.InterruptedException
method.getName(): wait
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
method.getName(): hashCode
public native int java.lang.Object.hashCode()
method.getName(): getClass
public final native java.lang.Class java.lang.Object.getClass()   
method.getName(): notify
public final native void java.lang.Object.notify()
method.getName(): notifyAll
public final native void java.lang.Object.notifyAll()

Person eating.....fries
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 实践 类名和包名

/*
  获取全类名和包名
  String getName()
  String getPackage()
 */
package com.peterjxl.reflect;

public class ReflectDemo5GetName {
  public static void main(String[] args) {
    Class personClass = Person.class;
    System.out.println("getName(): " + personClass.getName());  //getName(): com.peterjxl.reflect.Person
    System.out.println("getPackage(): " + personClass.getPackage());  //getPackage(): package com.peterjxl.reflect
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 实践 小型 Spring

需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

改代码的弊端:修改了代码后,需要重新测试,部署上线

实现方法:配置文件 + 反射

步骤:

  • 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
  • 在程序中加载读取配置文件
  • 使用反射技术来加载类文件进内存
  • 创建对象
  • 执行方法

新建 pro.properties 文件

className=cn.itcast.domain.Student
methodName=sleep
1
2
package com.peterjxl.reflect;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectSpring {
  public static void main(String[] args) throws Exception {

    // 1.加载配置文件
    // 1.1创建Properties对象
    Properties pro = new Properties();

    // 1.2加载配置文件,转换为一个集合
    // 1.2.1获取class目录下的配置文件
    ClassLoader classLoader = ReflectSpring.class.getClassLoader(); // 首先获取类加载器
    InputStream is = classLoader.getResourceAsStream("pro.properties"); // 然后通过类加载器,获取文件的字节流
    pro.load(is);

    // 2.获取配置文件中定义的数据
    String className = pro.getProperty("className");
    String methodName = pro.getProperty("methodName");

    // 3.加载该类进内存
    Class cls = Class.forName(className);
    // 4.创建对象
    Object obj = cls.newInstance();
    // 5.获取方法对象
    Method method = cls.getMethod(methodName);
    // 6.执行方法
    method.invoke(obj);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

如果是在命令行下运行:需要将配置文件挪到执行命令的地方,目录结构如下:

bin
├── com
│   └── peterjxl
│       └── reflect
│           ├── Person.class
│           ├── ReflectDemo1GetClassObject.class
│           ├── ReflectDemo2GetMember.class
│           ├── ReflectDemo3GetConstructor.class
│           ├── ReflectDemo4GetMethods.class
│           ├── ReflectDemo5GetName.class
│           ├── ReflectSpring.class
│           └── Student.class
└── pro.properties
1
2
3
4
5
6
7
8
9
10
11
12
13

运行结果

java -cp . com.peterjxl.reflect.ReflectSpring
Person eating.....
1
2

其他加载文件的方式:

package com.peterjxl.reflect;

import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectDemo6Spring {

    public static void main(String[] args) throws Exception {

        //1.加载配置文件
        Properties properties = new Properties();
        try (FileInputStream fis = new FileInputStream("pro.properties")) {
            properties.load(fis);
        }catch (Exception e){
            e.printStackTrace();
        }

        // 2.执行,和上述例子一样
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        Class cls = Class.forName(className);
        Object obj = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(obj);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 其他注意事项

  • 使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)
  • setAccessible(true) 可能会失败。如果 JVM 运行期存在 SecurityManager,那么它会根据规则进行检查,有可能阻止 setAccessible(true)。例如,某个 SecurityManager 可能不允许对 java 和 javax 开头的 package 的类调用 setAccessible(true),这样可以保证 JVM 核心库的安全。
上次更新: 2024/10/1 18:45:09
反射的原理
反射小结

← 反射的原理 反射小结→

最近更新
01
吐槽一下《僵尸校园》
05-15
02
2025 年 4 月记
04-30
03
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式