• java学习笔记:反射


    One Day Day 的


    一、类的加载

    1. 加载 头次用到该类的时候会先加载到内存,生成一个class文件
    2. 检验 加载进去之后会检验是否符合语法规范之类的
    3. 初始化 用该类做事情

    二、反射机制

    在运行状态下,动态的获得一个类的信息,并且调用实例的属性和方法,我们称为java的反射机制

    2.1 获取Class对象的三种方法

    		//1.通过Class类的静态方法:forName("全限定路径名")
            Class<?> studentClass1 = Class.forName("Student");
            //2. 通过类的class静态属性
            Class<Student> studentClass2 = Student.class;
            //3. 通过实例的getClass()方法
            Student student = new Student(1,"idiot");
            Class<? extends Student> studentClass3 = student.getClass();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2 获得构造方法,属性和方法

    2.2.1获得构造方法Constructor

    方法说明
    public Constructor getConstructor(Class… parameterTypes)获取public修饰的指定参数类型所对应的构造方法
    public Constructor getDeclaredConstructor(Class… parameterTypes)获取指定参数类型所对应的任意构造方法
    public Constructor[] getConstructors()获取所有公共的构造方法
    public Constructor[] getDeclaredConstructors()获取所有构造方法

    2.2.2 获取属性Field

    方法说明
    public Field getField(String name)获取public修饰的指定名称变量
    public Field getDeclaredField(String name)获取指定名称的任意变量
    public Field[] getFields()获取所有公共的变量
    public Field[] getDeclaredFields()获取所有变量

    2.2.3 获取方法Method

    方法说明
    public Method getMethod(String name, Class… parameterTypes)获取指定名称和参数类型的一个public修饰的方法
    public Method getDeclaredMethod(String name, Class… parameterTypes)获取指定名称和参数类型的一个任意方法
    public Method[] getMethods()获取所有public修饰的方法
    public Method[] getDeclaredMethods()获取所有方法

    2.3 使用

    使用的时候会发现私有的不让用,这时候我们需要使用setAccessible(boolean flag)方法暴力访问。flag = true取消权限检查

    2.3.1 构造方法的使用newInstance(Object… initargs)

    //先获取构造方法
    Constructor<?> constructor = studentClass1.getConstructor(int.class, String.class);
    //利用constructor中的newInstance(Object... initargs)方法创建实例,注意到返回值是Object类
    Object idiot = constructor.newInstance(1, "idiot");
    //因此我们进行强转
    Student s = (Student) idiot;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来要展示暴力访问

    Constructor<?> constructor = studentClass1.getDeclaredConstructor();
    Object idiot = constructor.newInstance();
    Student s = (Student) idiot;
    
    • 1
    • 2
    • 3

    给出以下报错信息,原因是无参构造是私有构造方法

    Exception in thread “main” java.lang.IllegalAccessException: class Demo cannot access a member of class Student with modifiers “private”
    at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:355)
    at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:639)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:490)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
    at Demo.main(Demo.java:19)

    这时候我们需要使用setAccessible(boolean flag)方法暴力访问。flag = true取消权限检查

    Constructor<?> constructor = studentClass1.getDeclaredConstructor();
    //看到了没,就是它取消了权限检查
    constructor.setAccessible(true);
    Object idiot = constructor.newInstance();
    Student s = (Student) idiot;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.3.2 属性的使用get(Object o)和set(Object o,Object value)

    //和上面的很像的
    Field name = studentClass1.getField("name");
    //这个name是一个Field对象
    System.out.println(name);
    
    • 1
    • 2
    • 3
    • 4

    通过get(Object o)方法获得值,set(Object o,Object value)方法设置值

    Field name = studentClass1.getField("name");
    System.out.println(name);
    //得到null是正常的,这个s是无参构造出来的,用上面的student就没问题了
    System.out.println(name.get(s));
    name.set(s,"愚者");
    //可以看到我们直接修改了值
    System.out.println(s.name);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    //获得私有属性,就取消下权限,和获取时的方法有差别,剩下的完全一样。
    Field id = studentClass1.getDeclaredField("id");
    id.setAccessible(true);
    
    • 1
    • 2
    • 3

    2.3.3 方法的调用invoke(Object obj,Object… args)

    Method method = studentClass1.getMethod("ggM", String.class);
    //s是实例对象,上面set和get哪个也是要给一个实例对象
    Object fanHuiZhi = method.invoke(s, "我是方法的参数");
    //确定返回值类型的情况下可以强转的
    System.out.println(fanHuiZhi);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    Method method = studentClass1.getDeclaredMethod("syM", String.class);
    method.setAccessible(true);
    Object fanHuiZhi = method.invoke(s, "我是方法的参数");
    //确定返回值类型的情况下可以强转的
    System.out.println(fanHuiZhi);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、反射练习

    3.1 泛型擦除

    编译后的.class文件没有泛型的约束,所以可以利用反射去添加编译阶段不让添加的东西。

    3.2 反射配置文件

    这好像是一个很有用的知识点,但是目前只能了解

    嘿嘿嘿,练习…就是练习…但是我还没有练,练了以后写在评论区吧。想看我写的可以催一下我……

  • 相关阅读:
    南卡火力全开,发布骨传导百元旗舰标杆,升级蓝牙5.3,内置4G存储,开启运动新体验!
    【Python百日进阶-数据分析】Day122 - Plotly Figure参数: 散点图(四)
    【计算机视觉 | 目标检测】目标检测常用数据集及其介绍(八)
    2022/7/20
    力扣刷题-链表-翻转链表
    SaaSBase:K2是什么?
    【机器学习技巧】机器学习模型的两种存储方式:pickle与joblib模块
    【Linux】package ‘python-yaml‘ has no installation candidate 如何解决
    大唐杯学习笔记:Day10
    济南 章丘 科目三 资料 收集
  • 原文地址:https://blog.csdn.net/qq_52515420/article/details/136275629