Java高级01——反射

1. 什么是反射

反射是框架设计的灵魂

反射:在类运行期间,借助Reflection API 把类中成员抽取为其他类,取得任何类的内部信息,并能直接操作任意对象的属性和方法。

把类中成员抽取为其他类:把java类中的各种成分映射成一个个的Java对象,例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)

源文件:.java文件,存放在磁盘中

字节码文件:.class文件,同样存放在磁盘中

Java程序的执行包含两个阶段:编译阶段、运行阶段

编译阶段

.java(源码)——》使用JDK当中自带的**javac**.exe命令进行java程序的编译——》得到.class字节码文件【最终要执行的文件

以上源文件和字节码文件均存放在磁盘中

运行阶段:

JDK中的java.exe主要负责运行阶段

  1. java.exe命令会启动Java虚拟机(JVM)
  2. JVM会启动**类加载器(ClassLoader)**
  3. 类加载器会去硬盘上搜索类名.class文件,找到该文件
  4. 将该字节码文件装载到JVM中,以Class的形式存在
  5. JVM将该字节码文件解释成二进制数据
  6. 操作系统执行二进制和底层硬件平台进行交互

上述文件存放在内存中

在这里插入图片描述

2. 为什么使用反射

反射是为了解决在运行期间,对某个实例一无所知的情况下,如何调用其他方法或属性

反射使用的前提条件:必须先得到代表的字节码的Class

Idea通过反射获取类中所有的method方法对象,以提示框的形式列出

3. 获取Class反射类的方式

提供了三种获取Class反射类的方法

  • 第一种:通过类名.class属性
//1. 通过类名.class获取
        Class studentClass = Student.class;
  • 第二种:通过类路径获取【加载驱动时用过】
//2. 通过路径获取
        Class aClass = Class.forName("com.zmq.entity.Student");
  • 第三种:通过对象名获取反射类型
//3.通过对象获取
//创建一个类对象
        Student student=new Student();
//通过getClass方法获得Class反射类
        Class aClass1 = student.getClass();

4. Class类中常用的方法

  • newInstance:通过反射类创建类对象
//获取到反射类
        Class<Student> studentClass = Student.class;
        //通过反射类创建对象
        Student student = studentClass.newInstance();
        System.out.println(student);
  • getAnnotation:获取反射类上的注解对象
//获取反射类上面的所有注解
        MyAnnotation annotation = studentClass.getAnnotation(MyAnnotation.class);
        System.out.println(annotation.value());

getAnnotation()是Java中反射API中的一个方法,用于获取某个类、方法或字段的注解信息。可以通过该方法获取指定注解类型的注解实例。在使用该方法时,需要提供注解的Class对象作为参数,如果要获取某个方法或字段上的注解,则需要先获取该方法或字段的对象,再调用 getAnnotation()方法获取注解实例。

5. Method类对象中常用的方法

  • getDeclaredMethods():获取本类中定义的所有Methods类对象
//获取反射类
        Class<Student> studentClass = Student.class;
        //获取本类中的所有Method对象
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method m: declaredMethods) {
            System.out.println(m);
        }
        System.out.println("+++++++++++++++++++++++++");
  • getDeclaredMethod(“方法名”,参数类型):获取本类中指定的方法对象
//获取本类中指定的Method对象
        Method fun = studentClass.getDeclaredMethod("fun");
        System.out.println(fun);
        System.out.println("**********************");
  • getMethods():获取本类和父类中所有的public方法对象
 //获取本类和父类中的所有public方法
        Method[] methods = studentClass.getMethods();
        for (Method m:methods) {
            System.out.println(m);
        }
        System.out.println("");
  • getMethod(“方法名”,参数类型):获取本类和父类中指定的public方法对象
//获取本类和父类中指定的public方法
        Method show = studentClass.getMethod("show");
        System.out.println(show);
        System.out.println("--------------------");
        Method fun1 = studentClass.getMethod("fun");
        System.out.println(fun1);

6. Method类对象中常用的方法

Class<?>:?表示泛型通配符

  • invoke( Object obj, Object… args):调用类中的方法,返回该方法执行的结果。第一个参数表示执行方法的对象,第二个参数表示执行方法的方法参数
//获取反射类
        Class<Student> studentClass = Student.class;
        //通过反射类创建对象
        Object o = studentClass.newInstance();

        //获取本类和父类中指定的public方法
        Method age = studentClass.getMethod("ages",Integer.class);
        //通过invoke方法,执行该方法,返回该方法执行的结果
		//第一个参数表示执行方法的对象
        Object invoke = age.invoke(o, 25);
        System.out.println(invoke);

若在实体类方法中没有返回值,为void,打印输出上述invoke为null。若在上述基础上,方法提内有打印输出语句,则该语句会作为返回结果输出,打印输出invoke为null。

若有返回值,如String,打印输出对应结果

  • 暴力访问私有方法——通过getDeclaredMethod()获取指定的私有方法
    • setAccessible():暴力访问
//暴力访问private方法
        //获取指定的方法,私有的
        Method age1 = studentClass.getDeclaredMethod("age", int.class);
        //暴力访问
        age1.setAccessible(true);
        Object invoke1 = age1.invoke(o, 30);
        System.out.println(invoke1);

7. 获取Filed属性对象的方式

同获取Method方法类对象相似,也提供四种方法

  • getDeclaredFields():获取本类中的所有属性
//获取反射类
        Class<Student> studentClass = Student.class;
        //通过反射类创建对象
        Student student = studentClass.newInstance();
        //获取本类中的所有属性
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field f:declaredFields) {
            System.out.println(f.getName());
        }
        System.out.println("---------");
  • getDeclaredField(“属性名”):获取指定的属性
//获取指定的属性
        Field names = studentClass.getDeclaredField("names");
  • getFields():获取本类和父类的所有public属性
//获取本类和父类中的所有public属性
        Field[] fields = studentClass.getFields();
        for (Field f:fields) {
            System.out.println(f.getName());
        }
        System.out.println("+++++++++++++");
  • getField(“属性名”):获取本类和父类中指定的public属性
//获取本类和父类中指定的public属性
        Field names1 = studentClass.getField("names");
        System.out.println(names1);

8. Filed类中常用的方法

  • set(Object对象,值):为属性赋值
//获取反射类
        Class<Student> studentClass = Student.class;
        //通过反射类创建对象
        Student student = studentClass.newInstance();

        //获取指定的属性
        Field names = studentClass.getDeclaredField("names");
        //为属性赋值
        names.set(student,"lay");
        //获取私有属性
        Field sex = studentClass.getDeclaredField("sex");
        //暴力访问
        sex.setAccessible(true);
        //为属性赋值
        sex.set(student,"男");
        System.out.println(student);
        System.out.println("=================");
  • getName():获取属性名
//获取本类中的所有属性
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field f:declaredFields) {
            //获取属性名
            System.out.println(f.getName());
        }
        System.out.println("---------");
  • getAnnotation():获取属性上的注解对象
//获取本类中的所有属性
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field f:declaredFields) {
            //获取属性名
            System.out.println(f.getName());
            //获取属性上的注解
            MyAnnotation annotation = f.getAnnotation(MyAnnotation.class);
            String value = annotation.value();
            System.out.println(value);
        }
        System.out.println("---------");

获取的注解若返回类型为Annotation,则获取value值时需要强转为MyAnnotation

9. 案例

在properties属性文件中指定类的路径,通过反射完成类对象的创建以及类中属性的赋值

public class Test06 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        //1. 创建属性文件对象
        Properties properties=new Properties();
        //2. 读取属性文件
        //2.1 输入
        InputStream resourceAsStream = Test06.class.getClassLoader().getResourceAsStream("zmq.properties");
       //2.2 读取
        properties.load(resourceAsStream);
        //3. 属性类读取属性文件中指定的key的值
        String className = properties.getProperty("className");
        //4. 根据类路径得到反射对象
        Class<?> aClass = Class.forName(className);
        //5. 根据反射类创建对象
        Object o = aClass.newInstance();
        System.out.println(o);
        //6. 为属性赋值
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field f:declaredFields) {
            //暴力访问
            f.setAccessible(true);
            //为属性赋值
            f.set(o,new Random().nextInt(100)+"");
        }
        System.out.println(o);
    }
}

通过案例可以得知,反射是在运行时,对原来类一无所知的情况下执行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值