JavaStudy12(23章-反射)—B站hsp

发布于:2022-12-15 ⋅ 阅读:(472) ⋅ 点赞:(0)

JavaStudy12(23章-反射)—B站hsp

1.1 一个需求引出反射

1.1.1请看下面的问题

在这里插入图片描述

代码演示:

package com.hspedu.reflection.question;

import com.hspedu.Cat;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @ClassName ReflectionQuestion
 * @Author :BLWY-1124
 * @Date :2022/5/1 17:16
 * @Description:
 * 反射问题的引入
 * @Version: 1.0
 */
@SuppressWarnings({"all"})
public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //根据配置文件 re.properties指定信息,创建Cat对象并调用方法hi
        //回忆

        //传统方式 new 对象 =》 调用
        //Cat cat = new Cat();
        //cat.hi();
        //我们尝试做一做 -》明白反射

        //1. 使用Properties 类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));//com.hspedu.Cat
        String classfullpath = properties.get("classfullpath").toString(); //hi
        String methodName = properties.get("method").toString();
        System.out.println("classfullpath=" +classfullpath);
        System.out.println("method= " + methodName);

        //2.创建对象, 传统的方法行不通
        //new classfullpath();

        //3.使用反射机制解决
        //(1)加载类,返回Class类型的对象cls
        Class cls =Class.forName(classfullpath);
        //(2)通过cls获得到你加载的类 com.hspedu.Cat 的对象实例
        Object o = cls.newInstance();
        System.out.println(o.getClass()); //com.hspedu.Cat  运行类型
        //(3)通过cls 得到加载的类(com.hspedu.Cat)的 methodName(hi) 的方法对象
        //    即:在反射中,可以把方法视为对象(万物皆对象 )
        Method method = cls.getMethod(methodName);   //对象 :method
        // (4)通过 method 调用方法:即通过方法对象来实现调用方法
        method.invoke(o); // 传统方法 对象.方法() ,反射机制 方法.invoke(对象)

    }
}
/**
 * @ClassName Cat
 * @Author :BLWY-1124
 * @Date :2022/5/1 17:13
 * @Description:
 * @Version: 1.0
 */
public class Cat {
    private String name = "招财猫";
    public void hi(){//常用方法
        System.out.println("hi" + name);
    }

    public void cry(){//常用方法
        System.out.println("cry" + name);
    }
}

配置文件

在这里插入图片描述

1.2 反射机制

1.2.1 Java Reflection

在这里插入图片描述

1.2.2 Java 反射机制原理示意图!!!

在这里插入图片描述

1.2.3 Java 反射机制可以完成

在这里插入图片描述

1.2.4 反射相关的主要类

在这里插入图片描述

代码演示:

package com.hspedu.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;

/**
 * @ClassName Reflection01
 * @Author :BLWY-1124
 * @Date :2022/5/4 20:10
 * @Description:
 * @Version: 1.0
 */
public class Reflection01 {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();

        //3.使用反射机制解决
        //(1)加载类,返回Class类型的对象cls
        Class cls =Class.forName(classfullpath);
        //(2)通过cls获得到你加载的类 com.hspedu.Cat 的对象实例
        Object o = cls.newInstance();
        System.out.println(o.getClass()); //com.hspedu.Cat  运行类型
        //(3)通过cls 得到加载的类(com.hspedu.Cat)的 methodName(hi) 的方法对象
        //    即:在反射中,可以把方法视为对象(万物皆对象 )
        Method method = cls.getMethod(methodName);   //对象 :method
        // (4)通过 method 调用方法:即通过方法对象来实现调用方法
        method.invoke(o); // 传统方法 对象.方法() ,反射机制 方法.invoke(对象)

        //4.java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
        // 得到 name 字段
        // getField 不能得到私有的属性
       // Field name = cls.getField("name"); private
        Field ageField = cls.getField("age");
        System.out.println(ageField.get(o)); //传统写法 对象.成员变量  反射:成员变量对象.get(对象)

        //5.java.lang.reflect.Constructor: 代表类的构造方法, Constructor 对象表示构造器
        Constructor constructor = cls.getConstructor(); //()中可以指定构造器参数类型,返回无参构造
        System.out.println(constructor); //public com.hspedu.Cat()

        Constructor constructor1 = cls.getConstructor(String.class); //这里传入的就是 String.class类的Class对象
        System.out.println(constructor1); //public com.hspedu.Cat(java.lang.String)
    }
}
package com.hspedu;

/**
 * @ClassName Cat
 * @Author :BLWY-1124
 * @Date :2022/5/1 17:13
 * @Description:
 * @Version: 1.0
 */
public class Cat {
    private String name = "招财猫";
    public int age = 12;

    public Cat(String name) {
        this.name = name;
    }

    public Cat() {
    }

    public void hi(){//常用方法
        System.out.println("hi" + name);
    }

    public void cry(){//常用方法
        System.out.println("cry" + name);
    }
}

配置文件

在这里插入图片描述

1.2.5 反射优点和缺点

在这里插入图片描述

hi.setAccessible(true);//在反射调用方法时,取消访问检查 提升执行效率

代码演示:

package com.hspedu.reflection;

import com.hspedu.Cat;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @ClassName Reflection02
 * @Author :BLWY-1124
 * @Date :2022/5/4 20:38
 * @Description: 测试反射调用的性能,和优化方案
 * @Version: 1.0
 */
public class Reflection02 {
    public static void main(String[] args) throws NoSuchMethodException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        //Field
        // Method
        // Constructor
        m1();//传统
        m2();//反射
        m3();//取消访问检查
    }

    //传统方法来调用 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, NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException, InstantiationException {
        /*Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        Class cls = Class.forName(classfullpath);*/
        Class cls = Class.forName("com.hspedu.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));
    }
    //反射机制调用方法 hi  在反射调用方法时,取消访问检查
    public static void m3() throws ClassNotFoundException, NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException, InstantiationException {
        /*Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        Class cls = Class.forName(classfullpath);*/
        Class cls = Class.forName("com.hspedu.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("反射m2=" + (end - start));
    }
}

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

在这里插入图片描述

在这里插入图片描述

1.3 Class 类

1.3.1 基本介绍

在这里插入图片描述

在这里插入图片描述

代码演示:

package com.hspedu.reflection.class_;

import com.hspedu.Cat;

/**
 * @ClassName Class01
 * @Author :BLWY-1124
 * @Date :2022/5/5 10:17
 * @Description: 对 Class 类特点的梳理
 * @Version: 1.0
 */
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //看看 Class 类图
        // 1. Class 也是类,因此也继承 Object 类
        // Class
        // 2. Class 类对象不是 new 出来的,而是系统创建的
        // (1) 传统 new 对象
        /*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 cls01 = Class.forName("com.hspedu.Cat");

        //3. 对于某个类的 Class 类对象,在内存中只有一份,因为类只加载一次
        Class cls02 = Class.forName("com.hspedu.Cat");
        System.out.println(cls01.hashCode()); //460141958
        System.out.println(cls02.hashCode()); //460141958
        Class cls03 = Class.forName("com.hspedu.Dog");
        System.out.println(cls03.hashCode()); //1163157884

        
    }
}

1.3.2 Class 类的常用方法

在这里插入图片描述

1.3.3 应用实例: Class02.java

代码演示:

package com.hspedu.reflection.class_;

import com.hspedu.Car;

import java.lang.reflect.Field;
import java.util.Base64;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.class_
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-05  11:27
 * @Description: 演示Class类的常用方法
 */
public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

        String classPath = "com.hspedu.Car";
        //1.获取到 Car 类的 对应的 Class对象
        //<?> 表示不确定Java类型
        Class<?> cls = Class.forName(classPath);
        //2.输出
        System.out.println(cls); //显示对象,是哪个Class类的对象: com.hspedu.Car
        System.out.println(cls.getClass()); // cls 运行类型:java.lang.Class
        //3.得到包名
        System.out.println(cls.getPackage().getName()); // com.hspedu  cls对应的Class类在哪一个包下面
        //4. 得到 cls 对应类的全类名
        System.out.println(cls.getName()); // com.hspedu.Car
        //5.通过cls 生成对象实例
        //Object o = cls.newInstance();
        Car car = (Car) cls.newInstance();
        System.out.println(car); //Car{brand='宝马', price=550000, color='蓝色'}
        //6. 通过反射获得属性 brand
        Field brand = cls.getField("brand");
        System.out.println(brand.get(car)); //宝马
        //7.通过反射给属性赋值
        brand.set(car,"奔驰");
        System.out.println(brand.get(car)); //奔驰
        //8.得到所有的属性(字段)
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.print("\t" + field.getName()); //属性名称  //brand  price  color
        }
    }
}

1.4 获取 Class 类对象

在这里插入图片描述

在这里插入图片描述

代码演示:

package com.hspedu.reflection.class_;

import com.hspedu.Car;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.class_
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-05  12:09
 * @Description: 演示得到Class的各种方式
 */
public class GetClass {
    public static void main(String[] args) throws ClassNotFoundException {
        //1. Class.forName
        /*Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();*/
        String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取
        Class<?> cls1 = Class.forName(classAllPath);
        System.out.println(cls1); //class com.hspedu.Car

        //2. 类名.class , 应用场景: 用于参数传递
        Class<Car> cls2 = Car.class;
        System.out.println(cls2);//class com.hspedu.Car

        //3.对象.getClass(), 应用场景,有对象实例
        Car car = new Car();
        Class cls3 = car.getClass();
        System.out.println(cls3); //class com.hspedu.Car

        //4. 通过类加载器【4 种】来获取到类的 Class 对象
        // (1)先得到类加载器 car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2)通过类加载器得到 Class 对象
        Class<?> cls4 = classLoader.loadClass(classAllPath);
        System.out.println(cls4); // class com.hspedu.Car

        //cls1 , cls2 , cls3 , cls4 其实是同一个对象
        System.out.println(cls1.hashCode()); //356573597
        System.out.println(cls2.hashCode()); //356573597
        System.out.println(cls3.hashCode()); //356573597
        System.out.println(cls4.hashCode()); //356573597

        //5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到 Class 类对象
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        Class<Boolean> booleanClass = boolean.class;
        System.out.println(integerClass); //int 自动装箱和拆箱
        System.out.println(characterClass); //char
        System.out.println(booleanClass); //boolean

        //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
        Class<Integer> integerClass1 = Integer.TYPE;
        Class<Character> characterClass1 = Character.TYPE;
        Class<Boolean> booleanClass1 = Boolean.TYPE;
        System.out.println(integerClass1); //int  自动装箱和拆箱
        //是同一个class对象
        System.out.println(integerClass.hashCode()); //1735600054
        System.out.println(integerClass1.hashCode()); //1735600054

    }
}

1.5 哪些类型有 Class 对象

1.5.1 如下类型有 Class 对象

在这里插入图片描述

代码演示:

package com.hspedu.reflection.class_;

import java.io.Serializable;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.class_
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-05  13:09
 * @Description: 演示哪些类型有 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); //class java.lang.String
        System.out.println(cls2); //interface java.io.Serializable
        System.out.println(cls3); //class [Ljava.lang.Integer;
        System.out.println(cls4); //class [[F
        System.out.println(cls5); //interface java.lang.Deprecated
        System.out.println(cls6); //class java.lang.Thread$State
        System.out.println(cls7); //long
        System.out.println(cls8); //void
        System.out.println(cls9); //class java.lang.Class
    }
}

1.6 类加载

1.6.1 基本说明

在这里插入图片描述

代码演示

import java.util. *;
import java.lang.relfect. *;
        public class ClassLoad_ {
            public static void mian(String[] args) throws Exception {
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入key");
                String key = scanner.next();
                switch (key) {
                    case "1":
                        //Dog dog = new Dog(); //静态加载,依赖性强,在编译时就要加载一遍
                        //dog.cry();
                        break;
                    case "2":
                        //反射-》动态加载
                        Class cls = Class.forName("Person");//加载Person
                        Object o = cls.newInstance();
                        Method m = cls.getMethod("hi");
                        m.invoke(o);
                        System.out.println("ok");
                        break;
                    default:
                        java
                        System.out.println("nothing");

                }
            }
        }

在这里插入图片描述

在这里插入图片描述

1.6.2 类加载时机

在这里插入图片描述

1.6.3 类加载过程图

在这里插入图片描述

1.6.4 类加载各阶段完成任务

在这里插入图片描述

1.6.5 加载阶段

在这里插入图片描述

1.6.6 连接阶段-验证

在这里插入图片描述

1.6.7 连接阶段-准备

在这里插入图片描述

1.6.8 连接阶段-解析

在这里插入图片描述

1.6.9 Initialization(初始化)

在这里插入图片描述

代码演示:

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.classload_
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-05  20:07
 * @Description: 演示类加载-初始化阶段
 */
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.7 通过反射获取类的结构信息

1.7.1 第一组: java.lang.Class 类

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

代码演示:

package com.hspedu.reflection;

import org.junit.jupiter.api.DynamicTest;
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;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-05  21:14
 * @Description: 演示如何通过反射获取类的结构信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    //第一组方法API
    @Test
    public void api_01() throws ClassNotFoundException {
        //得到 Class 对象
        Class<?> personCls = Class.forName("com.hspedu.reflection.Person");

        //getName:获取全类名
        System.out.println(personCls.getName()); //com.hspedu.reflection.Person

        //getSimpleName:获取简单类名
        System.out.println(personCls.getSimpleName());//Person

        //getFields:获取所有 public 修饰的属性,包含本类以及父类的
        Field[] fields = personCls.getFields();
        System.out.println("本类以及父类的属性=");
        for (Field field : fields) { //增强for循环
            System.out.print("\t" + field.getName());//name    hobby
        }

        //getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        System.out.println("本类中所有属性=");
        for (Field declaredField : declaredFields) {
            System.out.print("\t" + declaredField.getName());
            //本类中所有属性= name    age    job    sal
        }

        //getMethods:获取所有 public 修饰的方法,包含本类以及父类的
        Method[] methods = personCls.getMethods();
        System.out.print("本类以及父类的方法=");
        for (Method method : methods) {
            System.out.print("\t" + method.getName());
            //本类以及父类的方法=   m1 hi  wait   wait   wait   equals toString   hashCode   getClass   notify notifyAll
        }

        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        System.out.println("本类所有的方法=");
        for (Method declaredMethod : declaredMethods) {
            System.out.print("\t" + declaredMethod.getName());
            //本类所有的方法= m1 m2 m4 m3
        }

        //getConstructors: 获取所有 public 修饰的构造器,包含本类
        Constructor<?>[] constructors = personCls.getConstructors();
        System.out.println("本类的构造器=");
        for (Constructor<?> constructor : constructors) {
            System.out.print("\t" + constructor.getName());
            //本类的构造器=com.hspedu.reflection.Person  com.hspedu.reflection.Person
        }

        //getDeclaredConstructors:获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        System.out.println("本类中所有构造器=");
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.print("\t" + declaredConstructor.getName()); //这里只是输出名
            //本类中所有构造器= com.hspedu.reflection.Person   com.hspedu.reflection.Person   com.hspedu.reflection.Person
        }

        //getPackage:以 Package 形式返回 包信息
        Package aPackage = personCls.getPackage();
        System.out.println(aPackage.getName());//com.hspedu.reflection

        //getSuperClass:以 Class 形式返回父类信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父类的 class 对象=" + superclass);//class java.lang.Object

        //getInterfaces:以 Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        System.out.println("接口信息=");
        for (Class<?> anInterface : interfaces) {
            System.out.print("\t" + anInterface);
            //interface com.hspedu.reflection.IA   interface com.hspedu.reflection.IB
        }

        //getAnnotations:以 Annotation[] 形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息=" + annotation); //注解
            //注解信息=@java.lang.Deprecated()
        }

    }

    @Test
    public void api_02() throws ClassNotFoundException {

        //得到 Class 对象
        Class<?> personCls = Class.forName("com.hspedu.reflection.Person");

        //第二组:java.lang.reflect.Field 类
        //getModifiers: 以int形式返回修饰符
        //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());//属性对应的类的class对象
            //本类中所有属性=name 该属性的修饰符值= 1 该属性的类型=class java.lang.String
            //本类中所有属性=age 该属性的修饰符值= 12 该属性的类型=int
            //本类中所有属性=job 该属性的修饰符值= 0 该属性的类型=class java.lang.String
            //本类中所有属性=sal 该属性的修饰符值= 2 该属性的类型=double
        }


        //第三组: java.lang.reflect.Method 类
        //getModifiers: 以int形式返回修饰符
        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法=" + declaredMethod.getName() +
                    " 该方法的访问修饰符值=" + declaredMethod.getModifiers() +
                    " 该方法返回类型" + declaredMethod.getReturnType());
            //本类中所有方法=m1 该方法的访问修饰符值=1 该方法返回类型void
            //本类中所有方法=m2 该方法的访问修饰符值=4 该方法返回类型class java.lang.String
            //本类中所有方法=m4 该方法的访问修饰符值=2 该方法返回类型void
            //本类中所有方法=m3 该方法的访问修饰符值=0 该方法返回类型void

            //输出当前这个方法的形参数组情况  m1的形参情况  m2m3m4没有形参
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该方法的形参类型=" + parameterType);
                //该方法的形参类型=class java.lang.String
                //该方法的形参类型=int
                //该方法的形参类型=double
            }
        }

        //第四组: java.lang.reflect.Constructor 类
        //getModifiers: 以int形式返回修饰符
        //getConstructors: 获取所有 public 修饰的构造器,包含本类
        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);
            }
            //====================
            //本类中所有构造器=com.hspedu.reflection.Person
            //该构造器的形参类型=class java.lang.String
            //该构造器的形参类型=int
            //====================
            //本类中所有构造器=com.hspedu.reflection.Person
            //该构造器的形参类型=class java.lang.String
            //====================
            //本类中所有构造器=com.hspedu.reflection.Person
        }
    }
}
    class A {
        public String hobby;

        public void hi() {
        }
    }

    interface IA {
    }

    interface IB {
    }

    @Deprecated
    class Person extends A implements IA, IB {
        //属性
        public String name;
        protected static int age; // 4 + 8 = 12
        String job;
        private double sal;

        //构造器
        public Person() {
        }

        public Person(String name) {
        }

        //私有的构造器
        private 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.8 通过反射创建对象

在这里插入图片描述

1.8.1 案例演示 com.hspedu.reflection ReflecCreateInstance.java

  • 测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
  • 测试 2:通过调用某个特定构造器的方式,实现创建某类的对象

代码演示

package com.hspedu.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.channels.ClosedSelectorException;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-06  10:32
 * @Description: 演示通过反射机制创建实例
 */
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1. 先获取到 User 类的 Class 对象
        Class<?> userCls = Class.forName("com.hspedu.reflection.User");
        //2. 通过 public 的无参构造器创建实例
        Object o = userCls.newInstance();
        System.out.println(o); // User [age=10, name=韩顺平教育]
        //3. 通过 public 的有参构造器创建实例
       /*
       constructor 对象就是
        public User(String name) {//public 的有参构造器
        this.name = name;
    }*/
        //3.1 先得到对应构造器
        Constructor<?> constructor = userCls.getConstructor(String.class);
        //3.2 创建实例,并传入实参
        Object hsp = constructor.newInstance("hsp");
        System.out.println("hsp= " + hsp); //hsp= User [age=10, name=hsp]
        //4. 通过非 public 的有参构造器创建实例
        // 4.1 得到 private 的构造器对象
        Constructor<?> declaredConstructor = userCls.getDeclaredConstructor(int.class, String.class);
        //4.2 创建实例
        //暴破【暴力破解】 , 使用反射可以访问 private 构造器/方法/属性, 反射面前,都是纸老虎
        declaredConstructor.setAccessible(true);
        Object user2 = declaredConstructor.newInstance(100, "张三");
        System.out.println("user2=" + user2);//user2=User [age=100, name=张三]

    }
}

class User { //User 类
    private int age = 10;
    private String name = "韩顺平教育";

    public User() {//无参 public
    }

    public User(String name) {//public 的有参构造器
        this.name = name;
    }

    private User(int age, String name) {//private 有参构造器
        this.age = age;
        this.name = name;
    }

    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

1.9 通过反射访问类中的成员

1.9.1 访问属性 ReflecAccessProperty.java

在这里插入图片描述

代码演示:

package com.hspedu.reflection;

import java.lang.reflect.Field;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-06  11:36
 * @Description: 演示反射操作属性
 */
public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //1. 得到 Student 类对应的 Class 对象
        Class<?> studentCls = Class.forName("com.hspedu.reflection.Student");
        //2. 创建对象
        Object o = studentCls.newInstance();//o 的运行类型就是 Student
        System.out.println(o.getClass());//class com.hspedu.reflection.Student
        //3. 使用反射得到 age 属性对象
        Field age = studentCls.getField("age");
        age.set(o,55);
        System.out.println(o); //Student [age=55, name=null]
        System.out.println(age.get(o));//返回 age 属性的值  55
        //4. 使用反射操作 private name 属性
        Field name = studentCls.getDeclaredField("name");
        //对 name 进行暴破, 可以操作 private 属性
        name.setAccessible(true);
        name.set(o,"覃波");
        System.out.println(o);//Student [age=55, name=覃波]
        name.set(null, "老韩~");//因为 name 是 static 属性,因此 o 也可以写出 null
        System.out.println(o); //Student [age=55, name=老韩~]
        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() {//构造器
    }

    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
}

1.9.2 访问方法 ReflecAccessMethod.java

在这里插入图片描述

代码演示:

package com.hspedu.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-06  12:57
 * @Description: 演示通过反射调用方法
 */
public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1. 得到 Boss 类对应的 Class 对象
        Class<?> bossCls = Class.forName("com.hspedu.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, "韩顺平教育"); //hi 韩顺平教育
        //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, 5, "你好", 'A'));//5 你好 A
        //4.3 因为 say 方法是 static 的,还可以这样调用 ,可以传入 null
        System.out.println(say.invoke(null, 7, "你好", 'A'));//7 你好 A
        //5. 在反射中,如果方法有返回值,统一返回 Object , 但是他运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 30, "你好", '男');
        System.out.println("reVal 的运行类型=" + reVal.getClass());//reVal 的运行类型=class java.lang.String
        //在演示一个返回的案例 
        Method m1 = bossCls.getDeclaredMethod("m1");
        Object reVal2 = m1.invoke(o);
        System.out.println("reVal2 的运行类型=" + reVal2.getClass());//reVal2 的运行类型=class com.hspedu.reflection.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.10 本章作业

在这里插入图片描述

代码演示:

package com.hspedu.reflection.homework;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.homework
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-06  14:02
 * @Description:
 */
public class HomeWork01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
        //Class<?> privateTestClass = Class.forName("com.hspedu.reflection.homework.PrivateTest");
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        Object o = privateTestClass.newInstance();
        Field name = privateTestClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"hsp");
        Method getName = privateTestClass.getDeclaredMethod("getName");
        System.out.println(getName.invoke(o)); //hsp
    }
}
class PrivateTest{
    private String name = "helloKitty";

    public String getName() {
        return name;
    }
}

在这里插入图片描述

代码演示:

package com.hspedu.reflection.homework;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @BelongsProject: chapte23r
 * @BelongsPackage: com.hspedu.reflection.homework
 * @Author: 别来无恙qb
 * @CreateTime: 2022-05-06  14:22
 * @Description:
 */
public class HomeWork02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //Class<File> fileClass = File.class;
        Class<?> fileClass = Class.forName("java.io.File");
        Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
            //public java.io.File(java.lang.String,java.lang.String)
            //public java.io.File(java.lang.String)
            //private java.io.File(java.lang.String,java.io.File)
            //public java.io.File(java.io.File,java.lang.String)
            //public java.io.File(java.net.URI)
            //private java.io.File(java.lang.String,int)
        }
        //指定得到 java.io.File(java.lang.String)
        Constructor<?> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
        String fileAllPath = "e:\\mynew.txt";
        Object file = declaredConstructor.newInstance(fileAllPath); //创建File对象
        //file得运行类型就是File
        System.out.println(file.getClass());
        Method createNewFile = fileClass.getDeclaredMethod("createNewFile");
        createNewFile.invoke(file);
        System.out.println("创建文件成功" + fileAllPath);
    }
}

我亦无他,惟手熟尔


网站公告

今日签到

点亮在社区的每一天
去签到