Java - 反射技术(Reflect) , 框架设计的灵魂 ! 还不懂的点进来 。(重中之重)

反射: 框架设计的灵魂.

反射的前提: 类进入到内存中.
反射: 我们可以使用class文件对象 , 获取class文件中的成员变量 , 成员方法 , 构造方法 .
反射的好处: 对于任何一个类 , 都可以使用相同的方式获取.

类加载器:

注: java 运行的 都 是 c l a s s 文 件.
 
类加载器会做两件事:
        1.会把.class文件加载到内存中的方法区中!
        2.会为 class文件创建一个对象!
 
class文件对象: 是由类加载器创建 , 我 们 无 权 创 建 和 销 毁.

1.获取Class文件对象: (只有一个)

  • Class.forName(“全类名”) : 通过指定的字符串路径获取.
  • 类名.class(): 通过类名的属性class获取.
  • 对象.getClass(): 通过对象的getClass()方 法获取
     

注:3个获取方式获取的都是同一个文件对象(地址值一样.)

Student类:

public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("1. 调用公共的无参数的构造方法 ... ...");
    }

    public Student(String name) {
        this.name = name;
        System.out.println("2. 调用公共的有参数的(String name)构造方法 ... ...");
    }

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("3. 调用私有的有参数的(String name, int age)构造方法 ... ...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类: 获取class文件对象.

	@Test
    public void test02() throws ClassNotFoundException {
        /**
         *  需求: 获取指定类的字节码对象.
         */
        // 方式一: 类名.class.
        Class<Student> clazz01 = Student.class;
        System.out.println(clazz01);  // class com.aaa.reflect.Student

        // 方式二: 对象.getClass();    何为对象?   new出来的就是对象.
        Student student = new Student("张三");
        Class<? extends Student> clazz02 = student.getClass();
        System.out.println(clazz02);  // class com.aaa.reflect.Student


        // 方式三: Class.forName(类的全限定名)
        Class<?> clazz03 = Class.forName("com.aaa.reflect.Student");
        System.out.println(clazz03); // class com.aaa.reflect.Student

        // 注: 三个方法获取的都是同一个字节码对象.
    }

Class对象相关的API:
        String getSimpleName(); 获得简单类名,只是类名,没有包
        String getName(); 获取完整类名,包含包名+类名
        T newInstance() ;创建实例化对象。        要求:类必须有public的无参数构造方法

2.获取构造方法对象:

  • getConstructors(): 获取所有的public修饰的构造方法.
  • getConstructor(Class…parame): 只能获取public修饰的构造方法.
  • newInstance(Object…initargs): 根据指定参数创建对象.
  • setAccessible(true): 设置为可以直接访问私有类型的构造方法.

举个例子:

	@Test
    public void test03() throws Exception {
        /**
         *  需求: 通过反射new对象.
         *       方式一: 通过构造方法获取对象.
         */
        // 1.获取类的字节码对象.
        Class<?> clazz = Class.forName("com.aaa.reflect.Student");
        // 2.获取构造方法对象.
        Constructor<?> constructor = clazz.getConstructor();
        // 3.执行.
        Student stu01 = (Student) constructor.newInstance();
        System.out.println(stu01);


        /**
         *  方式二: 通过无参数构造方法直接获取对象. (使用的是Class对象的方法) 
         *     使用前提: 必须要有无参构造方法.
         */
        Class<?> clazz02 = Class.forName("com.aaa.reflect.Student");
        Student stu02 = (Student) clazz02.newInstance();
        System.out.println(stu02);
    }

3.获取成员方法对象:

  • getMethods(): 获取所有的public修饰的成员方法 , 包括父类中 .
  • getMethod(“方法名” , 方法的参数类型…类型): 获取一个方法类型.
  • invoke(Object obj,Object…args):根据参数ars调用对象obj的成员方法.

举个例子:

	@Test
    public void test04() throws Exception {
        /**
         *  需求: 通过调用setName方法 设置姓名
         */
        // 1.获取类的字节码对象.
        Class<?> clazz = Class.forName("com.aaa.reflect.Student");
        // 2.获取对象.
        Student stu = (Student) clazz.newInstance();
        // 3.获取类中的setname方法.
        Method method = clazz.getMethod("setName", String.class);
        // 4.使用Method类中的方法invoke执行获取到的成员方法
        method.invoke(stu, "老王");
        System.out.println(stu);  // Student{name='老王', age=0}
    }

 

反射综合案例:

/*
    反射综合案例
    我们可以
        创建Person对象,调用eat方法
        创建Student对象,调用study方法
        创建Worker对象,调用work方法
    要求:
        不修改代码,只能创建一个对象,调用3个类的方法
 */
public class Test {
    public static void main(String[] args) throws Exception {
        // 1. 创建properties对象.
        Properties prop = new Properties();
        // 2. 使用load方法读取文件.
        prop.load(new FileReader("day13_reflect\\prop.txt"));
        // 3. 使用集合中的getProperty方法, 通过key获取值.
        String className = prop.getProperty("className"); // 获取路径名.
        String methodName = prop.getProperty("methodName"); // 获取方法名.
        
        // 4. 使用获取到的全类名,通过Class类的forName方法获取class文件对象
        Class<?> clazz = Class.forName(className);
        // 5. 创建实例化对象.
        Object o = clazz.newInstance();
        // 6 .使用方法.
        Method method = clazz.getMethod(methodName);
        method.invoke(o);
    }
}

prop.txt:
className=demo03_reflectTest.Person
methodName=eat
className=demo03_reflectTest.Student
methodName=study
className=demo03_reflectTest.Worker
methodName=work
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值