• java反射机制详解


    在这里插入图片描述

    📖个人介绍


    大家好我是:一颗松
    认真分享技术,记录学习点滴
    如果分享对你有用请支持我哦🍺

    点赞:👍 留言:✍收藏:⭐️
    个人格言: 想法落实的最佳时机就是现在!🏄


    1 反射快速上手案例

    public class ReflectionQuestion {
        public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    //        创建properties对象
            Properties properties = new Properties();
    //        加载文件
            properties.load(new FileReader("E:\\Codes\\myProject\\JiShiTongXun\\reflectionDemo\\re.properties"));
    //        获取值
            String classpaht = properties.getProperty("classpaht");
            String method = properties.getProperty("method");
            System.out.println(classpaht);
    //        使用反射机制创建类
    //        ①加载类
            Class aClass = Class.forName(classpaht);
    //        ②通过得到的aClass对象,可以得到加载的类(配置文件中的类)的实例
            ReflectionDemo rfd = (ReflectionDemo) aClass.newInstance();
    //        ③得到方法的对象
            Method method1 = aClass.getMethod(method);
    //        ④通过方法对象,调用方法
            method1.invoke(rfd);
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2 使用反射的步骤

    第一步:载Class类,会返回一个Class类型的对象

    //①加载Class类,会返回一个Class类型的对象
            Class aClass = Class.forName("加载类全路径");
    
    • 1
    • 2

    第二步:通过Class类对象,得到需要加载的类Dog类的对象实例

    //①加载Class类,会返回一个Class类型的对象
                Class aClass = Class.forName(classpahttset);
    
    • 1
    • 2

    第三步:通过aClass得到加载类的Method对象

    // ③通过aClass得到加载类(Dog)的Method对象
            Method sayColor = aClass.getMethod("方法名");
    
    • 1
    • 2

    第四步:通过Method对象,调用方法

    //④通过Method对象,调用方法
            sayColor.invoke(aClass); 
    
    • 1
    • 2

    3 反射详解:

    在这里插入图片描述


    反射相关的主要类:
    (1) java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
    (2) java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法
    (3) java.lang.reflect.Field:代表类的成员变量
    (4) java.lang.reflect.Constructor:代表类的构造方法;

    4 反射的优化

    Method、Field、Constructor都有setAccessible()方法
    setAccessible方法是为了启动和禁止访问安全检查的开关
    参数为true,表示反射的对象在访问时取消检查,提高反射效率。参数为false时,表示执行访问检查。

    //        优化反射
            sayColor.setAccessible(true);
    
    • 1
    • 2

    5 Class类特点梳理

    在这里插入图片描述


    (1)Class也是一个类,它的父类也是Object
    (2)Class类对象不是new出来的,而是系统创建的
    (3)对于某个类的Class对象,在内存中只能存在一份,因为类只加载一次;
    (4)每个类的实例都会知道自己是由哪个Class类生成
    (5)通过Class类对象可以得到一个类的完整结构;
    (6)Class对象存放在堆上
    (7)类的字节码二进制文件是存放在方法区的

    6 Class类的常用方法

    public class ClassDemo {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
            Class aClass = Class.forName("com.zinksl.reflectionDemo.reflection01.Dog");
            //        获取包名
            String packgname = aClass.getPackage().getName();
            System.out.println(packgname);
            //        获取全类名
            System.out.println(aClass.getName());
            //        通过Class对象,创建需求类对象示例
            Dog dog = (Dog)aClass.newInstance();
            //        通过反射获取属性
            Field color = aClass.getField("color");
            String colors = (String) color.get(dog);
            System.out.println(colors);
            //        通过反射给属性设置值
            color.set(dog,"黄色");
            //        通过反射获取所有属性
            Field[] fields = aClass.getFields();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    7 获取Class类的方式

    7.1 在编译阶段获取Class类对象,通过Class.forName()方法

    如果已知全类名,则可以通过forName()方法获取
    应用场景:用于配置文件,读取全类名,路径加载类

    7.2 在类加载阶段可以通过,类名.class获取

    应用场景:多用于参数传递,如:通过反射得到对于构造器对象;

    7.3 在运行阶段可以通过,对象名.getClass()方法获取

    7.4 通过类加载器获取Class对象

    8 java中哪些类有Class对象

    (1)成员内部类、静态内部类、局部内部类、匿名内部类
    (2)Interface:接口
    (3)数组
    (4)枚举
    (5)annotation:注解
    (6)基本数据类型
    (7)void

    9 类加载

    【反射是java实现动态语言的关键,也是通过反射实现动态加载的】
    类加载可分为静态加载和动态加载
    静态加载,在编译期就加载类,如果找不到就报错,依赖性比较强
    动态加载,在运行时加载需要的类,如果运行时用不到该类,就算找不到也不报错,依赖性比较弱

    10 通反射获取类的结构信息:

    方法名说明
    getName获取全类名
    getSimpleName获取简单类名
    getFields获取所有public修饰的属性,包括本类及父类
    getDeclardeFields获取本类所有属性
    getMethods获取所有public修饰的方法,包括本类及父类
    getDeclardeMethods获取本类所有方法
    getConstructors获取所有public修饰的构造器,包括本类
    getDeclardeConstructors获取本类所有构造器
    getPackage以Package形式返回包信息
    getSuperClass以Class形式返回父类信息
    getInterfaces以Class[]形式返回接口信息
    getAnnotations以Annotation[] 形式返回注解信息

    代码演示

    public class ReflectionTest {
        public static void main(String[] args) {
    
        }
        @Test
        public void api() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    
    
    //        getMethods	获取所有public修饰的方法,包括本类及父类
    //        getDeclardeMethods	获取本类所有方法
    //        getConstructors	获取所有public修饰的构造器,包括本类及父类
    //        getDeclardeConstructors	获取本类所有构造器
    //        getPackage	以Package形式返回包信息
    //        getSuperClass	以Class形式返回父类信息
    //        getInterfaces	以Class[]形式返回接口信息
    //        getAnnotations	以Annotation[] 形式返回注解信息
    //        1首先得到对应的Class对象
            Class<?> aClass = Class.forName("com.zinksl.reflectionDemo.reflectionTest.Person");
    //        2 得到目标类对象
            Person person = (Person) aClass.newInstance();
    //        getName	获取全类名
    //        getSimpleName	获取简单类名
            String name = aClass.getName();
            System.out.println("全类名:"+name);
            System.out.println("简单类名:"+aClass.getSimpleName());
    //        getFields	获取所有public修饰的属性,包括本类及父类
    //        getDeclardeFields	获取本类所有属性
            Field[] fields = aClass.getFields();
            for (Field f:fields){
                System.out.println("本类及父类的所有共有属性:"+f.getName());
            }
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println("本类所有属性:"+declaredField.getName());
            }
        }
    }
    class Person{
        public String name;
        public int age;
        private String hoby;
    
        public Person() {
        }
    
        public Person(String name, int age, String hoby) {
            this.name = name;
            this.age = age;
            this.hoby = hoby;
        }
        public void sayHello(){
            System.out.println("hello");
        }
        private void sayHi(){
            System.out.println("hi");
        }
    
        /**
         * 获取
         * @return name
         */
        public String getName() {
            return name;
        }
    
        /**
         * 设置
         * @param name
         */
        public void setName(String name) {
            this.name = name;
        }
    
        /**
         * 获取
         * @return age
         */
        public int getAge() {
            return age;
        }
    
        /**
         * 设置
         * @param age
         */
        public void setAge(int age) {
            this.age = age;
        }
    
        /**
         * 获取
         * @return hoby
         */
        public String getHoby() {
            return hoby;
        }
    
        /**
         * 设置
         * @param hoby
         */
        public void setHoby(String hoby) {
            this.hoby = hoby;
        }
    
        public String toString() {
            return "Person{name = " + name + ", age = " + age + ", hoby = " + hoby + "}";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    11 java.lang.reflect.Field类

    (1)getModifiers:以int形式返回修饰符
    【说明:默认修饰符:0,public:1,private:2,
    protected:4,static:8,final:16;public static:1+8】
    (2)getType:以Class形式返回类型
    (3)getName:返回方法名

    12 java.lang.reflect.Method类

    (1)getModifiers:以int形式返回修饰符
    【说明:默认修饰符:0,public:1,private:2,
    protected:4,static:8,final:16;public static:1+8】
    (2)getReturnType:以Class形式返回类型
    (3)getName:返回方法名
    (4)getParameterType:以Class[] 返回参数类型数组

    13 java.lang.reflect.Constructor类

    (1)getModifiers:以int形式返回修饰符
    【说明:默认修饰符:0,public:1,private:2,
    protected:4,static:8,final:16;public static:1+8】
    (4)getParameterType:以Class[] 返回参数类型数组
    (3)getName:返回构造器名(全类名)

    13 通过反射创建对象

    (1) 调用类中被public修饰的无参构造

    (2)调用类中指定的构造器

    (3)Class类相关方法

    ①newInstance :调用类中无参构造器,获取对应类对象
    ②getConstructor(Class…):根据参数列表获取对应的构造器对象
    ③getDecalaredConstructor(Class…):根据参数列表获取对应的构造器对象

    (4)Constructor类相关方法

    ①setAccessible;爆破
    ②newInstance(Object…):调用构造器
    代码示例:

    public class ReflectGetObject {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    //        1 先获取Person类的Class对象
            Class personClass = Class.forName("com.zinksl.reflectionDemo.reflectGetObject.Person");
    //        2通过public无参构造器,创造实例
            Object o = personClass.newInstance();
            System.out.println(o);
    //        3通过public有参构造器,创造实例
            //①先得到构造器
            Constructor constructor = personClass.getConstructor(String.class);
            //②通过构造器创建实例
            Object o1 = constructor.newInstance("马云");
            System.out.println(o1);
    //        4 通过私有构造器,创造实例
            //先得到构造器
            Constructor constructor1 = personClass.getDeclaredConstructor(String.class,int.class,String.class);
    //        爆破
            constructor1.setAccessible(true);//使用反射,创建私有化构造器,对象
            Object o2 = constructor1.newInstance("大黄", 80, "溜圈");
            System.out.println(o2);
    
        }
    }
    class Person{
        private String name ="码云";
        private int age = 20;
        public String hoby;
    
        public Person() {
        }
        public Person(String name){
            this.name = name;
        }
    
    
        private Person(String name, int age, String hoby) {
            this.name = name;
            this.age = age;
            this.hoby = hoby;
        }
    
        /**
         * 获取
         * @return name
         */
        public String getName() {
            return name;
        }
    
        /**
         * 设置
         * @param name
         */
        public void setName(String name) {
            this.name = name;
        }
    
        /**
         * 获取
         * @return age
         */
        public int getAge() {
            return age;
        }
    
        /**
         * 设置
         * @param age
         */
        public void setAge(int age) {
            this.age = age;
        }
    
        /**
         * 获取
         * @return hoby
         */
        public String getHoby() {
            return hoby;
        }
    
        /**
         * 设置
         * @param hoby
         */
        public void setHoby(String hoby) {
            this.hoby = hoby;
        }
    
        public String toString() {
            return "Person{name = " + name + ", age = " + age + ", hoby = " + hoby + "}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    14 通过反射访问类中成员

    (1) 根据属性名 获取Field对象

    Field f = Class对象.getDeclaredField(属性名);

    (2)爆破 f.setAccessible(true); f是 Field的对象;

    (3)访问

    f.set(o,值);o表示对象
    syso(f.get(o)); o表示对象

    (4)如果是静态属性,则set、get中的o属性,可以设置为null;

    代码示例:

    public class ReflectionGetShuxing {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, InstantiationException {
    //1获得Class类对象
            Class<?> aClass = Class.forName("com.zinksl.reflectionDemo.reflectGetObject.Person2");
    //        2创建对象
            Object o = aClass.newInstance();
    //        3 获取Field的对象
            Field hoby = aClass.getField("hoby");
    //        4 设置属性
            hoby.set(o,"抽烟喝酒烫头");
            System.out.println(o);
            Field age = aClass.getDeclaredField("age");
            age.setAccessible(true);
            age.set(o,9999);
            System.out.println(o);
    
    
        }
    }
    class Person2{
        private static String name ="码云";
        private int age = 20;
        public String hoby;
    
        public Person2() {
        }
        public Person2(String name){
            this.name = name;
        }
    
    
        private Person2(String name, int age, String hoby) {
            this.name = name;
            this.age = age;
            this.hoby = hoby;
        }
    
        /**
         * 获取
         * @return name
         */
        public String getName() {
            return name;
        }
    
        /**
         * 设置
         * @param name
         */
        public void setName(String name) {
            this.name = name;
        }
    
        /**
         * 获取
         * @return age
         */
        public int getAge() {
            return age;
        }
    
        /**
         * 设置
         * @param age
         */
        public void setAge(int age) {
            this.age = age;
        }
    
        /**
         * 获取
         * @return hoby
         */
        public String getHoby() {
            return hoby;
        }
    
        /**
         * 设置
         * @param hoby
         */
        public void setHoby(String hoby) {
            this.hoby = hoby;
        }
    
        public String toString() {
            return "Person{name = " + name + ", age = " + age + ", hoby = " + hoby + "}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    结语

    大佬请留步在这里插入图片描述既然看到这了不如点个赞👍再走吧

    本文目的在于分享技术以及在学习过程中个人记得需要注意的点,记录学习过程;
    如果出现错误欢迎大家指正,如有意见或建议欢迎在评论区讨论

  • 相关阅读:
    如何使用轻量应用服务器自带的Cloudreve应用镜像搭建属于自己的云网盘?
    码蹄集 - MT3252 - 子序列问题
    SpringBoot技术在商场应急管理中的创新应用
    腾讯云~Kafka 监控 Kafka Eagle 图形化版本
    达美乐面试(部分)(未完全解析)
    算法设计与分析算法实现——棋盘覆盖问题
    分支路径图调度框架在vivo效果广告业务的落地实践
    jdk的安装及环境配置
    【正点原子STM32连载】 第四十章 DAC输出三角波实验 摘自【正点原子】APM32F407最小系统板使用指南
    c#文件读写
  • 原文地址:https://blog.csdn.net/Zinkse/article/details/126067745