反射原理剖析笔记

反射:框架设计的灵魂

本笔记为个人学习笔记,仅供学习。视频链接:https://www.bilibili.com/video/BV1C4411373T
框架:半成品软件。可以在框架的基础上进行软件开发,简化编码

反射:将类的各个组成部分封装为其他对象,这就是反射机制

一.Java代码在计算机经历的三个阶段:

在这里插入图片描述

使用反射好处:

  1. 可以在程序运行过程中,操作这些对象。(例子:代码提示时弹出自定义方法)
  2. 可以解耦,提高程序的可扩展性。
二. 获取Class对象的方式:
  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

多用于配置文件,将类名定义在配置文件中。读取文件,加载类

  1. 类名.class:通过类名的属性class获取

多用于参数的传递

  1. 对象.getClass():getClass()方法在Object类中定义着。

多用于对象的获取字节码的方式

​ 每个阶段对应一种方法:

在这里插入图片描述

测试代码:

package reflect;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一:Class.forName("全类名")
        Class aClass = Class.forName("reflect.Person");
        System.out.println(aClass);
        //2. 类名.class:通过类名的属性class获取
        Class aClass1 = Person.class;
        System.out.println(aClass1);
        //3. 对象.getClass():getClass()方法在Object类中定义着。
        Person person=new Person();
        Class aClass2 = person.getClass();
        System.out.println(aClass2);
        //比较三个对象
        System.out.println(aClass==aClass1);//true
        System.out.println(aClass==aClass2);//true
        System.out.println(aClass1==aClass2);//true
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Person{
    private String name;
    private int age;
}

结论:

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

三. Class对象功能:

获取功能:

  1. 获取成员变量们

    • Field[] getFields() :获取所有public修饰的成员变量

    • Field getField(String name) 获取指定名称的 public修饰的成员变量

    • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符

    • Field getDeclaredField(String name)

  2. 获取构造方法们

  • Constructor<?>[] getConstructors()

  • Constructor getConstructor(类<?>… parameterTypes)

  • Constructor getDeclaredConstructor(类<?>… parameterTypes)

  • Constructor<?>[] getDeclaredConstructors()

  1. 获取成员方法们:
  • Method[] getMethods()

  • Method getMethod(String name, 类<?>… parameterTypes)

  • Method[] getDeclaredMethods()

  • Method getDeclaredMethod(String name, 类<?>… parameterTypes)

  1. 获取全类名
  • String getName()
1.Field:成员变量

操作:

		//1. 设置值
			 void set(Object obj, Object value)//  
		//2. 获取值
			 get(Object obj) 
		//3. 忽略访问权限修饰符的安全检查
			*setAccessible(true):暴力反射

代码:

/*
1. 获取成员变量们
   - Field[] getFields() :获取所有public修饰的成员变量
   - Field getField(String name)   获取指定名称的 public修饰的成员变量
   - Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
   - Field getDeclaredField(String name)
   */
public class ReflectFields {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class personClass = Person.class;
        
        //Field[] getFields() :获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println("   "+field);
        }
        
        //Field getField(String name):获取指定名称的 public修饰的成员变量
        Field pub=personClass.getField("pub");
        System.out.println(pub);

        //获取成员变量的值
        Person person=new Person();
        Object value=pub.get(person);
        System.out.println("value = [" + value + "]");

        //设置pub的值
        pub.set(person,"KAKA");
        System.out.println("pub = [" + person.getPub() + "]");
        
        //Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField:declaredFields) {
            System.out.println("   "+declaredField);
        }
        
        // - Field getDeclaredField(String name)
        Field pri = personClass.getDeclaredField("pri");
        
        //忽略访问权限修饰符的安全检查:暴力反射
        pri.setAccessible(true);
        Object value2=pri.get(person);
        System.out.println("value2 = [" + value2 + "]");

    }
}
2. Constructor:构造方法

操作:

T newInstance(Object... initargs)  

// 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

代码:

/*
 2. 获取构造方法们
   - Constructor<?>[] getConstructors()
   - Constructor<T> getConstructor(类<?>... parameterTypes)
   - Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
   - Constructor<?>[] getDeclaredConstructors()
 */

public class ReflectConstructors {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class personClass = Person.class;

        //Constructor<?>[] getConstructors()
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println("constructor = [" + constructor + "]");

        //创建对象
        Object kaka = constructor.newInstance("kaka", 22);
        System.out.println("person="+kaka);

        //空参构造
        Constructor constructor1 = personClass.getConstructor();
        System.out.println("constructor1 = [" + constructor1 + "]");
        Object kaka1 = constructor1.newInstance();
        System.out.println("person="+kaka1);

        //简化空参构造
        Object kaka3=personClass.newInstance();
        System.out.println("person = [" + kaka3 + "]");
    }
}

3. Method:方法对象
//执行方法:
 Object invoke(Object obj, Object... args)  
//获取方法名称:
 String getName:获取方法名

代码:

/*
3. 获取成员方法们:
   - Method[] getMethods()
   - Method getMethod(String name, 类<?>... parameterTypes)
   - Method[] getDeclaredMethods()
   - Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4. 获取全类名
   - String getName()
 */
public class ReflectMethosd {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class personClass = Person.class;

        //Method getMethod(String name, 类<?>... parameterTypes)
        Person person=new Person();
        Method eat_method = personClass.getMethod("eat");
        eat_method.invoke(person);
        //加入方法参数
        Method eat_method1 = personClass.getMethod("eat",String.class);
        eat_method1.invoke(person,"rice");

        //Method[] getMethods()
        Method[] methods = personClass.getMethods();
        for (Method m:methods) {
            //获取方法名
            System.out.print(m.getName()+"===>");
            System.out.println("[" + m + "]");
        }

        //获取类名
        String className = personClass.getName();
        System.out.println("className = [" + className + "]");

    }
}

四. 案例:

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

   实现:
   
   - 配置文件
   - 反射
   
   步骤:
   
   1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
   2. 在程序中加载读取配置文件
   3. 使用反射技术来加载类文件进内存
   4. 创建对象
   5. 执行方法

项目架构:

在这里插入图片描述
代码:

pro.properties:

className=reflectExample.Student
methodName=sleep

ReflectExampleTest.class

package reflectExample;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

//不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
public class ReflectExampleTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1.加载配置文件
        //1.1创建Properties对象
        Properties properties=new Properties();
        ClassLoader classLoader = ReflectExampleTest.class.getClassLoader();
        //注意maven项目配置文件要放在Resources下
        InputStream resource = classLoader.getResourceAsStream("pro.properties");
        properties.load(resource);
        //2.获取配置文件中定义的数据
        String className = properties.getProperty("className");
        String methodName =properties.getProperty("methodName");
        //3.反射加载该类进内存
        Class aClass = Class.forName(className);
        //4.创建对象
        Object o = aClass.newInstance();
        //5.获取方法对象
        Method method = aClass.getMethod(methodName,int.class);
        //6.执行方法
        method.invoke(o,9);

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值