java反射机制基础

举报
花花叔叔 发表于 2022/08/14 22:37:26 2022/08/14
【摘要】 文章目录 反射概述反射获取类对象反射获取构造器对象反射获取成员变量对象反射获取方法对象绕过编译阶段为集合添加数据反射做通用框架 反射概述 反射就是对于任何一个Class类,在“运行的时候”...

反射概述

反射就是对于任何一个Class类,在“运行的时候”都是可以直接得到这个类的全部成分的。

在运行时,可以直接得到这个类的构造器对象:Constructor
在运行时,可以直接得到这个类的成员变量对象:Field
在运行时,可以直接得到这个类的成员方法对象:Method
这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

反射机制的关键:反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分

HelloWorld.java -> javac -> HelloWorld.class
Class c = HelloWorld.class;

本质上其实就是.class文件就是一个类对象。

反射的基本作用:在运行时获取类的字节码文件对象,然后解析类中的全部成分。
反射的核心思想和关键就是:得到编译以后的class文件对象。

class在内存中的结构
在这里插入图片描述

反射获取类对象

反射的第一步就是要获取Class类的对象
在这里插入图片描述
在这里插入图片描述
方式一:Class c1 = Class.forName(“全类名”);
方式二:Class c2 = 类名.class
方式三:Class c3 = 对象.getClass();

    @Test
    public void test1() {

        Student student1 = new Student();

        Student student2 = new Student();
//        第一种获取类对象的方法
        Class<?> s1 = null;

        try {
            s1 = Class.forName("Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

//        第二种获取类对象的方法
        Class<Student> s2 = Student.class;

//        第三种获取类对象的方法
        Class<? extends Student> s3 = student1.getClass();

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

    }

在这里插入图片描述

反射获取构造器对象

使用反射技术获取构造器对象并使用
在这里插入图片描述
API
在这里插入图片描述

    @Test
    public void test2() throws NoSuchMethodException {

        Class<Student> sc = Student.class;

//        1. 拿到所有的构造器
        Constructor<?>[] constructors = sc.getDeclaredConstructors();

//        输出构造器的名称+参数个数
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName() + " 参数个数:" + constructor.getParameterCount() + "个");
        }

//        2. 拿到单个构造器
        Constructor<Student> constructor = sc.getDeclaredConstructor(String.class, String.class);

        System.out.println(constructor.getName() + "参数个数:" + constructor.getParameterCount());

    }

使用反射技术获取构造器对象并使用获取到的内容创建出一个对象

反射得到构造器之后的作用仍是创建一个对象,如果说构造器是public,就可以直接new对象,如果说是构造器是私有的private,需要提前将构造器进行暴力反射,再进行构造对象。

反射是可以直接破换掉封装性的,私有的也是可以执行的。
在这里插入图片描述

//        3. 使用无参构造器创建对象
        Student o = (Student)constructors[0].newInstance();
        System.out.println(o);

//        4. 使用全参数构造器创建对象

        constructor.setAccessible(true);  // 暴力反射

        Student student = constructor.newInstance("孙悟空", "20");

        System.out.println(student.getName() + student.getAge());

反射获取成员变量对象

在这里插入图片描述
在这里插入图片描述
参数是变量名
在这里插入图片描述
赋值操作时候,需要先选定是哪一个对象,之后将要赋的值给他即可,获取值的时候,需要先找到要获取哪一个对象的值。

//        给成员变量name赋值
        Student student = new Student();  // 首先要new出一个对象来,这样纸才知道是给哪个对象的哪一个成员变量赋值

        field.setAccessible(true);

        field.set(student,"齐天大圣");

        System.out.println(student.getName());

        String name= (String) field.get(student);

        System.out.println(name);

这里也可以使用暴力反射的方式获取。

反射获取方法对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Test
    public  void test5() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        Class<Student> sc = Student.class;

        Method[] methods = sc.getDeclaredMethods();

        for (Method method : methods) {
            String name = method.getName();
            System.out.println(name);
        }

        Method eat = sc.getDeclaredMethod("eat", String.class);

        Student student = new Student();

        Object invoke = eat.invoke(student, "小狗");

        System.out.println(invoke);

        Method eat1 = sc.getDeclaredMethod("eat", String.class,String.class);

        Object invoke1 = eat1.invoke(student, "小狗", "吃好吃的");

        System.out.println(invoke1);

    }

在这里插入图片描述

绕过编译阶段为集合添加数据

反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素
泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。
可以通过对象获取class类,之后找到add方法,之后再调用add方法。

@Test
    public void test6() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        ArrayList<String> list = new ArrayList<>();

        list.add("lala");

        System.out.println(list);

        Class aClass = list.getClass();

        Method add = aClass.getDeclaredMethod("add", Object.class);

        add.invoke(list,1);

        System.out.println(list);

    }

反射做通用框架

需求:给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文件中去。
定义一个方法,可以接收任意类的对象。
每次收到一个对象后,需要解析这个对象的全部成员变量名称。
这个对象可能是任意的,那么怎么样才可以知道这个对象的全部成员变量名称呢?
使用反射获取对象的Class类对象,然后获取全部成员变量信息。
遍历成员变量信息,然后提取本成员变量在对象中的具体值
存入成员变量名称和值到文件中去即可。

文章来源: blog.csdn.net,作者:花花叔叔,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_52077949/article/details/122789155

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。