java反射机制基础

反射概述

反射就是对于任何一个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类对象,然后获取全部成员变量信息。
遍历成员变量信息,然后提取本成员变量在对象中的具体值
存入成员变量名称和值到文件中去即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java反射机制是指在程序运行时动态地获取一个的信息,包括的属性、方法和构造函数等,并能够在运行时调用这些属性和方法,而不需要事先知道这个具体信息。Java反射机制是实现框架(如Spring)的基础,它使得我们可以在不修改原有代码的情况下,动态地创建对象、调用方法、获取属性等操作,从而实现程序的灵活性和扩展性。 Java反射机制的核心是Class,每个都有一个对应的Class对象,它包含了该的所有信息,包括名、方法、属性等。通过Class对象可以获取的信息,并对进行操作。 Java IOC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建、管理、依赖关系的维护等工作交给容器来完成,从而实现了组件之间的松耦合和可重用性。Java IOC的核心是容器,容器负责管理各个组件之间的依赖关系,并在需要的时候动态地创建和注入对象Java IOC的实现依赖于反射机制,容器通过反射机制获取的信息,并通过构造函数或setter方法来创建和注入对象Java IOC的好处是可以将各个组件解耦,使得程序更加灵活和可扩展,同时也提高了代码的可测试性和可维护性。 综上所述,Java反射机制是实现Java IOC的基础Java IOC利用反射机制来实现对象的动态创建和注入。反射机制和IOC的合理运用可以使程序更加灵活和可扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花叔叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值