• 反射知识点学习



    image-20230928163222663

    1. Java 反射机制原理示意图

    image-20230928163240928

    • Java反射机制可以完成

    image-20230928163343071

    1.1 反射相关的主要类

    image-20230928163416900

    package com.xjz.reflection;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class Reflection01 {
        public static void main(String[] args) throws Exception {
    
            //1. 使用 Properties 类,可以读写配置文件
            Properties properties = new Properties();
            properties.load(new FileInputStream("src\\re.properties"));
            String classfullpath = properties.get("classfullpath").toString(); // "com.xjz.Cat"
            String methodName = properties.get("method").toString(); //"hi"
    
            //2. 使用反射机制解决
            //(1) 加载类,返回 Class 类型的对象 cls
            Class cls = Class.forName(classfullpath);
            //(2) 通过 cls 得到你加载的类 com.xjz.Cat 的对象实例
            Object o = cls.newInstance();
            System.out.println("o 的运行类型=" + o.getClass());//运行类型
            //(3) 通过 cls 得到你加载的类 com.xjz.Cat 的 methodName “hi” 的方法对象
            //    即:在反射中,可以把方法视为对象(万物皆对象)
            Method method = cls.getMethod(methodName);
            //(4) 通过 method 调用方法:即通过方法对象类实现调用方法
            System.out.println("=======================");
            method.invoke(o); //传统对象 对象.方法(),反射机制 方法.invoke(对象)
            //java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
            //得到 name 字段
            //getField 不能得到私有的属性
            Field ageField = cls.getField("age");
            System.out.println(ageField.get(o));//传统写法 对象.成员变量 , 反射:成员变量对象.get(对象)
    
            //java.lang.reflect.Constructor: 代表类的构造方法, Constructor 对象表示构造器
            Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,返回无参构造器
            System.out.println(constructor);//public com.xjz.Cat()
    
            Constructor constructor2 = cls.getConstructor(String.class);//这里传入的 String.class 就是 String类的 Class对象
            System.out.println(constructor2); //public com.xjz.Cat(java.lang.String)
    
        }
    }
    
    • 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

    1.2 反射的优点和缺点

    image-20230928170555665

    1.3 反射调用优化-关闭访问检查

    image-20230928171454966

    image-20230928171547125

    package com.xjz.reflection;
    
    import com.xjz.Cat;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 测试反射调用的性能,和优化方案
     */
    public class Reflection02 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    
    //        Field
    //        Method
    //        Constructor
            //上面三个类都继承了 AccessibleObject类
            m1(); //传统  0ms
            m2(); //反射  1750ms
            m3(); //反射优化    1268ms
    
    
        }
    
        //传统方法来调用 hi
        public static void m1() {
            Cat cat = new Cat();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 900000000; i++) {
                cat.hi();
            }
            long end = System.currentTimeMillis();
            System.out.println("m1() 耗时=" + (end - start));
        }
    
        //反射机制调用方法 hi
        public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            Class cls = Class.forName("com.xjz.Cat");
            Object o = cls.newInstance(); //实例化反射对象
            Method hi = cls.getMethod("hi");
            long start = System.currentTimeMillis();
            for (int i = 0; i < 900000000; i++) {
                hi.invoke(o);//反之调用方法
            }
            long end = System.currentTimeMillis();
            System.out.println("m2() 耗时=" + (end - start));
        }
    
        //反射调用优化 + 关闭访问检查
        public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            Class cls = Class.forName("com.xjz.Cat");
            Object o = cls.newInstance(); //实例化反射对象
            Method hi = cls.getMethod("hi");
            hi.setAccessible(true);//在反射调用方法时,取消访问检查,提高性能
            long start = System.currentTimeMillis();
            for (int i = 0; i < 900000000; i++) {
                hi.invoke(o);//反之调用方法
            }
            long end = System.currentTimeMillis();
            System.out.println("m3() 耗时=" + (end - start));
        }
    }
    
    • 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

    2. Class 类

    2.1 基本介绍

    image-20230928172213503

    image-20230928172250021

    package com.xjz.reflection.class_;
    
    import com.xjz.Cat;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 对 Class 类特点的梳理
     */
    public class Class01 {
        public static void main(String[] args) throws ClassNotFoundException {
            //看看 Class 类图
            //1. Class 也是类,因此也继承 Object 类
    //        Class
            //2. Class类对象不是 new 出来的,而是系统创建的
            //(1) 传统 new 对象
            /* ClassLoader 类
                public Class loadClass(String name) throws ClassNotFoundException {
                    return loadClass(name, false);
                }
             */
            //Cat cat = new Cat();
            //(2) 反射方式,刚才没有 debug 到 ClassLoader 类的loadClass,
            // 原因是 没有注销Cat cat = new Cat(); 即: 类只加载一次
            /*
                ClassLoader 类, 仍然是通过 ClassLoader 类加载 Cat 类的 Class 对象
                public Class loadClass(String name) throws ClassNotFoundException {
                    return loadClass(name, false);
                }
                */
            Class<?> cls1 = Class.forName("com.xjz.Cat");
    
            //3. 对于某个类的 Class类对象,在内存中只有一份,因为类只加载一次
            Class<?> cls2 = Class.forName("com.xjz.Cat");
            System.out.println(cls1.hashCode());//356573597
            System.out.println(cls2.hashCode());//356573597
            Class<?> cls3 = Class.forName("com.xjz.Dog");
            System.out.println(cls3.hashCode());//1735600054
        }
    }
    
    • 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

    2.2 Class类的常用方法

    image-20230928174347986

    package com.xjz.reflection.class_;
    
    import com.xjz.Car;
    
    import java.lang.reflect.Field;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示 Class 类的常用方法
     */
    public class Class02 {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
    
            String classAllPath = "com.xjz.Car";
            //1. 获取到 Car 类对应的 Class 对象
            // 表示不确定的 Java 类型
            Class cls = Class.forName(classAllPath);
            //2. 输出 cls
            System.out.println(cls);//显示 cls 对象,是哪个类的 Class 对象 即:class com.xjz.Car
            //3. 得到报名
            System.out.println(cls.getPackage().getName());//包名 com.xjz
            //4. 得到全类名
            System.out.println(cls.getName());//com.xjz.Car
            //5. 通过 cls 创建对象实例
            Car car = (Car) cls.newInstance();
            System.out.println(car); //car.toString()
            //6. 通过反射获取属性 brand
            Field brand = cls.getField("brand");
            System.out.println(brand.get(car));
            //7. 通过反射给属性赋值
            brand.set(car,"奔驰");
            System.out.println(brand.get(car));//奔驰
            //8. 我希望大家可以得到所有的属性(字段)
            System.out.println("======所有的属性字段======");
            Field[] fields = cls.getFields();
            for (Field f : fields) {
                System.out.println(f.getName()); //名称
            }
    
        }
    }
    
    • 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

    2.3 获取 Class 类对象

    image-20230928180145691

    image-20230928180151255

    image-20230928180157283

    package com.xjz.reflection.class_;
    
    import com.xjz.Car;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示得到 Class 对象的各种方式(6)
     */
    public class GetClass_ {
        public static void main(String[] args) throws ClassNotFoundException {
    
            //1. Class.forName
            String classAllPath = "com.xjz.Car";//通过读取配置文件获取
            Class<?> cls1 = Class.forName(classAllPath);
            System.out.println(cls1);
    
            //2. 类名.class,应用场景:用于参数传递
            Class cls2 = Car.class;
            System.out.println(cls2);
    
            //3. 对象.getClass(),应用场景:有对象实例
            Car car = new Car();
            Class cls3 = car.getClass();
            System.out.println(cls3);
    
            //4. 通过类加载器【4种】来获取到类的 Class 对象
            //(1) 先得到类加载器 car
            ClassLoader classLoader = car.getClass().getClassLoader();
            //(2) 通过类加载器得到 Class 对象
            Class cls4 = classLoader.loadClass(classAllPath);
            System.out.println(cls4);
    
            //cls1 , cls2 , cls3 , cls4 其实是同一个对象
            System.out.println(cls1.hashCode());
            System.out.println(cls2.hashCode());
            System.out.println(cls3.hashCode());
            System.out.println(cls4.hashCode());
    
            //5. 基本数据(int,char,boolean,float,double,byte,short,long) 按如下方式得到 Class 类对象
            Class<Integer> integerClass = int.class;
            Class<Character> characterClass = char.class;
            Class<Boolean> booleanClass = boolean.class;
            System.out.println(integerClass);//int
    
            //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
            Class<Integer> type1 = Integer.TYPE;
            Class<Character> type2 = Character.TYPE;//其它包装类 BOOLEAN, DOUBLE, LONG,BYTE 等等
            System.out.println(type1);
    
            System.out.println(integerClass.hashCode());//1735600054
            System.out.println(type1.hashCode());//1735600054
    
        }
    }
    
    • 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

    3. 哪些类型有 Class 对象

    image-20230928184711589

    package com.xjz.reflection.class_;
    
    import com.sun.org.apache.bcel.internal.classfile.Deprecated;
    
    import java.io.Serializable;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示哪些类型有 Class 对象
     */
    public class AllTypeClass {
        public static void main(String[] args) {
    
            Class<String> cls1 = String.class;//外部类
            Class<Serializable> cls2 = Serializable.class;//接口
            Class<Integer[]> cls3 = Integer[].class;//数组
            Class<float[][]> cls4 = float[][].class;//二维数组
            Class<Deprecated> cls5 = Deprecated.class;//注解
            //枚举
            Class<Thread.State> cls6 = Thread.State.class;
            Class<Long> cls7 = long.class;//基本数据类型
            Class<Void> cls8 = void.class;//void 数据类型
            Class<Class> cls9 = Class.class;//
    
            System.out.println(cls1);
            System.out.println(cls2);
            System.out.println(cls3);
            System.out.println(cls4);
            System.out.println(cls5);
            System.out.println(cls6);
            System.out.println(cls7);
            System.out.println(cls8);
            System.out.println(cls9);
        }
    }
    
    • 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

    4. 类加载

    4.1 基本说明

    image-20230928192003731

    4.2 类加载时机

    image-20230928192053660

    4.3 类加载过程图

    image-20230928192110265

    4.4 类加载各阶段完成任务

    image-20230928192132922

    4.5 加载阶段

    image-20230928192155241

    4.6 连接阶段-验证

    image-20230928192223356

    4.7 连接阶段-准备

    image-20230928192237893

    package com.xjz.reflection.classLoad_;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 我们说明一个类加载的链接阶段-准备
     */
    public class ClassLoad02 {
        public static void main(String[] args) {
            
        }
    }
    class A {
        //属性-成员变量-字段
        //分析类加载的链接阶段-准备 属性是如何处理
        //1. n1 是实例属性,不是静态变量,因此在准备阶段,是不会分配内存
        //2. n2 是静态变量,分配内存 n2 是默认初始化 0,而不是 20
        //3. n3 是 static final 是常量,他和静态变量不一样,因为一旦赋值就不变 n3 = 30
        public int n1 = 10;
        public static int n2 = 20;
        public static final int n3 = 30;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5. 连接阶段-解析

    image-20230928192623999

    6. Initialization(初始化)

    image-20230928192644741

    package com.xjz.reflection.classLoad_;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示类加载-初始化阶段
     */
    public class ClassLoad03 {
        public static void main(String[] args) {
    
            //代码分析
            //1. 加载 B 类,并生成 B 的 class 对象
            //2. 链接 num = 0
            //3. 初始化阶段
            // 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
            /*
                clinit() {
                    System.out.println("B 静态代码块被执行");
                    //num = 300;
                    num = 100;
                }
                合并: num = 100
            */
    
            //new B();//类加载
            //System.out.println(B.num);//100, 如果直接使用类的静态属性,也会导致类的加载
            //看看加载类的时候,是有同步机制控制
            /*
            protected Class loadClass(String name, boolean resolve)
            throws ClassNotFoundException
            {
                //正因为有这个机制,才能保证某个类在内存中, 只有一份 Class 对象
                synchronized (getClassLoadingLock(name)) {
                //.... }
            }
            */
            B b = new B();
        }
    }
    class B {
        static {
            System.out.println("B 静态代码块执行");
            num = 300;
        }
    
        static int num = 100;
    
        public B() {//构造器
            System.out.println("B() 构造器执行");
        }
    }
    
    
    • 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

    5. 通过反射获取类的结构信息

    5.1 第一组:java.lang.Class 类

    image-20230930151133200

    5.2 第二组:java.lang.reflect.Field 类

    image-20230930151234712

    5.3 第三组: java.lang.reflect.Method 类

    image-20230930151326302

    5.4 第四组:java.lang.reflect.Constructor 类

    image-20230930151502568

    package com.xjz.reflection;
    
    import org.junit.jupiter.api.Test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示如何通过反射获取类的结构信息
     */
    public class ReflectionUtils {
        public static void main(String[] args) {
    
        }
    
        @Test
        public void api_02() throws ClassNotFoundException {
    
            //得到 Class对象
            Class<?> personCls = Class.forName("com.xjz.reflection.Person");
            // getDeclaredFields: 获取本类中所有的属性
            //规定 说明: 默认修饰符 是 0 , public 是 1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16
            Field[] declaredFields = personCls.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println("本类中所有的属性=" + declaredField.getName()
                                + " 该属性的修饰符值=" + declaredField.getModifiers()
                                + " 该属性的类型=" + declaredField.getType());
            }
    
            //getDeclaredMethods:获取本类中所有方法
            Method[] declaredMethods = personCls.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println("本类中所有方法=" + declaredMethod.getName()
                                + " 该方法的访问修饰符值=" + declaredMethod.getModifiers()
                                + " 该方法返回类型=" + declaredMethod.getReturnType());
    
                //输出当前这个方法的形参数组情况
                Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    System.out.println("该方法的形参类型=" + parameterType);
                }
            }
    
            //getDeclaredConstructors:获取本类中所有构造器
            Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
            for (Constructor<?> declaredConstructor : declaredConstructors) {
                System.out.println("==============================================");
                System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里我们只输出名字
    
                Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    System.out.println("该构造器的形参类型=" + parameterType);
                }
            }
    
    
        }
    
        //第一组方法 API
        @Test
        public void api_01() throws ClassNotFoundException {
    
            //得到 Class对象
            Class<?> personCls = Class.forName("com.xjz.reflection.Person");
            // getName 获取全类名
            System.out.println(personCls.getName());//com.xjz.reflection.Person
            // getSimpleName:获取简单类名
            System.out.println(personCls.getSimpleName());//Person
            // getFields: 获取所有 public 修饰的属性,包含本类以及父类的
            Field[] fields = personCls.getFields();
            for (Field field : fields) { //增强for
                System.out.println("本类以及父类的属性=" + field.getName()); //name , hobby
            }
            // getDeclaredFields: 获取本类中所有的属性
            Field[] declaredFields = personCls.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println("本类中所有的属性=" + declaredField.getName());
            }
            // getMethods: 获取所有 public 修饰的方法,包含本类以及父类的
            Method[] methods = personCls.getMethods();
            for (Method method : methods) {
                System.out.println("本类以及父类的方法=" + method.getName());
            }
            //getDeclaredMethods:获取本类中所有方法
            Method[] declaredMethods = personCls.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println("本类中所有方法=" + declaredMethod.getName());
            }
            //getConstructors: 获取所有 public 修饰的构造器,包含本类
            Constructor<?>[] constructors = personCls.getConstructors();
            for (Constructor<?> constructor : constructors) {
                System.out.println("本类的构造器=" + constructor.getName());
            }
            //getDeclaredConstructors:获取本类中所有构造器
            Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
            for (Constructor<?> declaredConstructor : declaredConstructors) {
                System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里我们只输出名字
            }
            //getPackage:以 Package 形式返回 包信息
            System.out.println(personCls.getPackage());//com.hspedu.reflection
            //getSuperClass:以 Class 形式返回父类信息
            Class<?> superclass = personCls.getSuperclass();
            System.out.println("父类的 class对象=" + superclass);
            //getInterfaces:以 Class[]形式返回接口信息
            Class<?>[] interfaces = personCls.getInterfaces();
            for (Class<?> anInterface : interfaces) {
                System.out.println("接口信息=" + anInterface);
            }
            //getAnnotations:以 Annotation[] 形式返回注解信息
            Annotation[] annotations = personCls.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println("注解信息=" + annotation);//注解
            }
    
        }
    
    
    }
    class A {
        public String hobby;
    
        public void hi(){
    
        }
    
        public A(){}
    
        public A(String name){
    
        }
    }
    interface IA{
    }
    interface IB{
    
    }
    
    @Deprecated
    class Person extends A implements IA,IB{
        //属性
        public String name;
        protected static int age;
        String job;
        private double sal;
    
        //构造器
        public Person(){
    
        }
        public Person(String name){
    
        }
    
        //私有的
        public Person(String name,int age){
    
        }
    
        //方法
        public void m1(String name,int age,double sal){
    
        }
        protected String m2(){
            return null;
        }
        void m3(){
    
        }
        private void  m4(){
    
        }
    }
    
    • 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
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176

    6. 通过反射创建对象

    image-20230930151549506

    • 测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
    • 测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
    package com.xjz.reflection;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示通过反射机制创建实例
     */
    public class ReflecCreateInstance {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    
            //1. 先获取 User 类的 Class 对象
            Class<?> userClass = Class.forName("com.xjz.reflection.User");
            //2. 通过 public的无参构造器创建实例
            Object o = userClass.newInstance();
            System.out.println(o);
            //3. 通过 public 的有参构造器创建实例
            /*
                constructor 对象就是
                public User(String name) {//public 的有参构造器
                    this.name = name;
                }
             */
            //3.1 先得到对应构造器
            Constructor<?> constructor = userClass.getConstructor(String.class);
            //3.2 创建实例,并传入实参
            Object xjz = constructor.newInstance("xjz");
            System.out.println("xjz=" + xjz);
            //4. 通过非 public 的有参构造器创建实例
            //4.1 得到 private 的构造器对象
            Constructor<?> constructor2 = userClass.getDeclaredConstructor(int.class, String.class);
            //4.2 创建实例
            //暴破【暴力破解】,使用反射可以访问 private 构造器/方法/属性,反射面前,都是纸老虎
            constructor2.setAccessible(true);
            Object user2 = constructor2.newInstance(100, "张杰");
            System.out.println("user2=" + user2);
    
    
        }
    }
    
    class User { // User 类
        private int age = 10;
        private String name = "xjz_2002";
    
        public User() { //无参 public
        }
    
        public User(String name) { //public 的有参构造器
            this.name = name;
        }
    
        private User(int age, String name) { //private 有参构造器
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User[age" + age + ", name=" + name + ']';
        }
    }
    
    • 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

    7. 通过反射访问类中的成员

    7.1 访问属性 ReflecAccessProperty.java

    image-20230930151705599

    package com.xjz.reflection;
    
    import java.lang.reflect.Field;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示反射操作属性
     */
    public class ReflecAccessProperty {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
    
            //1. 得到 Student 类对应的 Class 对象
            Class<?> stuClass = Class.forName("com.xjz.reflection.Student");
            //2. 创建对象
            Object o = stuClass.newInstance();// o 的运行类型是 Student
            System.out.println(o.getClass());//Student
            //3. 使用反射得到 age 属性对象
            Field age = stuClass.getField("age");
            age.set(o,21);//通过反射来操作属性
            System.out.println(o);
            System.out.println(age.get(o));//返回 age属性的值
    
            //4. 使用反射操作 name 属性
            Field name = stuClass.getDeclaredField("name");
            //对 name 进行暴破,可以操作 private 属性
            name.setAccessible(true);
    //        name.set(o,"老徐");
            name.set(null,"老徐"); //因为 name 是 static 属性,因此 o 也可以写出 null
            System.out.println(o);
            System.out.println(name.get(o));//获取属性值
            System.out.println(name.get(null));//获取属性值,要求 name 是 static
    
    
        }
    }
    
    class Student { //类
        public int age;
        private static String name;
    
        public Student() { //构造器
        }
    
        @Override
        public String toString() {
            return "Student[age=" + age + ",name=" + name + ']';
        }
    }
    
    
    • 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

    7.2 访问方法 ReflecAccessMethod.java

    image-20230930151820601

    package com.xjz.reflection;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * @author xjz_2002
     * @version 1.0
     * 演示通过反射调用方法
     */
    public class ReflecAccessMethod {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    
            //1. 得到 Boos 类对应的 Class 对象
            Class<?> bossCls = Class.forName("com.xjz.reflection.Boss");
            //2. 创建对象
            Object o = bossCls.newInstance();
            //3. 调用 public 的 hi 方法
            //Method hi = bossCls.getMethod("hi", String.class);
            //3.1 得到 hi 方法对象
            Method hi = bossCls.getDeclaredMethod("hi", String.class);
            //3.2 调用
            hi.invoke(o,"张国荣");
    
            //4. 调用 private static 方法
            //4.1 得到 say 方法对象
            Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
            //4.2 因为 say 方法是 private,所有需要暴破,原理和前面的构造器和属性一样
            say.setAccessible(true);
            System.out.println(say.invoke(o,21,"xjz",'男'));
            //4.3 因为 say 方法是 static的,还可以这样调用,可以传入 null
            System.out.println(say.invoke(null,22,"tom",'女'));
    
            //5. 在反射中,如果方法有返回值,统一返回 Object,但是他运行类型和方法定义的返回类型一致
            Object reVal = say.invoke(null, 300, "王五", '男');
            System.out.println("reVal 的运行类型=" + reVal.getClass());//String
    
            //再演示一个返回的案例
            Method m1 = bossCls.getDeclaredMethod("m1");
            Object reVal2 = m1.invoke(o);
            System.out.println("reVal2 =运行类型=" + reVal2.getClass()); //Monster
    
    
        }
    }
    
    class Monster {
    }
    
    class Boss {//类
        public int age;
        private static String name;
    
        public Boss() {//构造器
        }
    
        public Monster m1() {
            return new Monster();
        }
    
        private static String say(int n, String s, char c) {//静态方法
            return n + " " + s + " " + c;
        }
    
        public void hi(String s) {//普通 public 方法
            System.out.println("hi " + s);
        }
    }
    
    
    • 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

    8. 本章作业

    image-20230930151849221

    package com.xjz.homework;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class Homework01 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    
            //1. 得到 PrivateTest类对应的 Class对象
            Class<PrivateTest> privateTestClass = PrivateTest.class;
            //2. 创建对象实例
            PrivateTest privateTestObj = privateTestClass.newInstance();
            //3. 得到 name 属性对象
            Field name = privateTestClass.getDeclaredField("name");
            //4. 暴破name
            name.setAccessible(true);
            name.set(privateTestObj,"xjz");
            //5. 得到getName方法对象
            Method getName = privateTestClass.getMethod("getName");
            //6. 因为getName() 是public,所有直接嗲用
            Object invoke = getName.invoke(privateTestObj);
            System.out.println("name属性值=" + invoke);
        }
    }
    
    class PrivateTest {
        private String name = "hellokitty";
        //默认无参构造器
        public String getName(){
            return name;
        }
    }
    
    • 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

    image-20230930151918622

    package com.xjz.homework;
    
    import java.io.File;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * @author xjz_2002
     * @version 1.0
     */
    public class Homework02 {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    
            //1. Class类的forName方法得到File类的 class对象
            Class<?> fileClass = Class.forName("java.io.File");
            //2. 得到所有的构造器
            Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
            //遍历输出
            for (Constructor<?> declaredConstructor : declaredConstructors) {
                System.out.println("File的类所有构造器=" + declaredConstructor);
            }
            //3. 指定得到 public java.io.File(java.lang.String)
            Constructor<?> constructor = fileClass.getConstructor(String.class);
            String fileAllPath = "d:\\mynew.txt";
            Object file = constructor.newInstance(fileAllPath); //创建File对象
    
            //4. 得到createNewFile 方法对象
            Method createNewFile = fileClass.getMethod("createNewFile");
            createNewFile.invoke(file);//创建文件,调用的是 createNewFile
            //file 的运行类型就是File
            System.out.println(file.getClass());//class java.io.File
            System.out.println("创建文件成功" + fileAllPath);
    
        }
    }
    
    • 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
  • 相关阅读:
    【雨夜】一次nacos 导致的 CPU 飙高问题
    一文探索【skywalking】如何通过agent实现启动流程
    Transforms的使用2(ToTensor类)
    java和vue视频点播系统视频弹幕系统
    【Python自学笔记】Flask调教方法Internel Server Error
    软件设计不是CRUD(9):低耦合模块设计理论——设计落地所面临的挑战
    HttpServletRequest接口详解,获取html用户输入的表单数据,HttpServletRequest请求域,请求转发机制
    第七版教材下的PMP考试有多难?
    Repo 使用详解
    【毕业设计】电商产品评论数据分析可视化(情感分析) - python 大数据
  • 原文地址:https://blog.csdn.net/m0_53125903/article/details/133434626