0
点赞
收藏
分享

微信扫一扫

加载器与反射

yongxinz 2022-04-21 阅读 41
java

一、加载器

* 类的加载器
* 启动类、扩展类、系统类
* 启动类(Bootstrap)负责启动jvm
* 扩展类(Extension)早期,扩展包
* 系统类(System)负责加载系统类路径
* 加载-验证-准备-解析-初始化
* 加载:类加载的一个过程:通过一个类的完全限定查找此类的字节码文件,并利用字节码文件创建一个class文件
* 验证:目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全,主要包含四种:文件格式验证,元数据验证,字节码验证符号引用验证
* 准备:为类变量分配内存并设置该类变量的初始值即0,这里不包含final修饰的static,因为final在编译的时候就分配了注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到java堆中
* 解析:将类的二进制数据中的符号引用替换成直接引用。说明一下:符号引用:符号引用是以一组符号来描述所引用的目标,符号可以是任何的字面形式的字面量,只要不会出现冲突能够定位到就行。布局和内存无关。直接引用:是指向目标的指针,偏移量或者能够直接定位的句柄。该引用是和内存中的布局有关的,并且一定加载进来的。
* 初始化:初始化是为类的静态变量赋予正确的初始值,准备阶段和初始化阶段看似有点矛盾,其实是不矛盾的,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。

    @Test
    public void test01(){

        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        //系统类的加载器
        //app
        System.out.println(systemClassLoader.getName());
        //扩展类加载器
        //platform
        System.out.println(systemClassLoader.getParent().getName());
        //启动类加载器
        //Cannot invoke "java.lang.ClassLoader.getName()" because the return value of "java.lang.ClassLoader.getParent()" is null
        //c/c++编写,底层代码,无法查看
        //System.out.println(systemClassLoader.getParent().getParent().getName());
    }

类的输出:以下五种

@Test
    public void test02(){
        //类名.class
        Class<Emp> empClass = Emp.class;
        //class com.lihaozhe.enmudemo.Emp
        System.out.println(empClass);
        //com.lihaozhe.enmudemo.Emp
        System.out.println(empClass.getName());
        //Emp
        System.out.println(empClass.getSimpleName());
    }
    @Test
    public void test03(){
        //实例化对象,实例化时会调用静态代码块
        Emp emp = new Emp();
        Class<? extends Emp> empClass = emp.getClass();
        System.out.println(empClass);
        System.out.println(empClass.getName());
        System.out.println(empClass.getSimpleName() );
    }
    @Test
    public void test04(){
        //Class.forName("全名"),会调用静态代码块
        try {
        Class<?> empClass = Class.forName("com.lihaozhe.enmudemo.Emp");
            System.out.println(empClass);
            System.out.println(empClass.getName());
            System.out.println(empClass.getSimpleName() );
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    @Test
    public void test05(){
        //通过类的加载器
        ClassLoader classLoader = Person.class.getClassLoader();
        try {
            Class<?> loadClass = classLoader.loadClass("com.lihaozhe.enmudemo.Emp");
            System.out.println(loadClass);
            System.out.println(loadClass.getName());
            System.out.println(loadClass.getSimpleName() );
        }catch (ClassNotFoundException e){
            throw new RuntimeException(e);
        }
    }
    @Test
    public void test06(){
        //基本数据类型
        Class<Integer> type = Integer.TYPE;
        System.out.println(type);
        System.out.println(type.getName());
        System.out.println(type.getSimpleName());
    }

二、反射

1、反射之类的调用

(1)

    @Test
    public void test01() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        // 2、使用该类的Class对象将该类实例化(java8之前)
        try {
            Emp emp = empClass.newInstance();
            emp.setName("李昊哲");
            System.out.println(emp.getName());
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

(2)

@Test
    public void test02() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2 获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 3、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            emp.setName("李昊哲");
            System.out.println(emp.getName());
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

(3)

    @Test
    public void test03() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2 获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor(String.class, Integer.class, Integer.class);
            // 3、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance("李昊哲", 18, 1);
            System.out.println(emp);
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

2、反射之方法调用

(1)

    @Test
    public void test04() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、根据方法名字获取该类中的方法
            Method method = empClass.getMethod("haha");
            // 3、执行该类中的方法
            method.invoke(empClass);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

(2)

@Test
    public void test05() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、根据方法名字获取该类中的方法
            Method method = empClass.getMethod("heihei");
            // 3 获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 4、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            // 5、执行该类中的方法
            method.invoke(emp);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
                InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

(3)

    @Test
    public void test06() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、根据方法名字获取该类中的方法
            Method method = empClass.getDeclaredMethod("hehe");
            // 3 获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 4、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            // 5、设置方法可以访问权限
            method.setAccessible(true);
            // 6、执行该类中的方法
            method.invoke(emp);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
                InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

(4)

    @Test
    public void test07() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、根据方法名字获取该类中的方法
            Method method = empClass.getDeclaredMethod("sum", Integer.class, Integer.class);
            // 3 获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 4、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            // 5、设置方法可以访问权限
            method.setAccessible(true);
            // 6、执行该类中的方法
            Integer num = (Integer) method.invoke(emp, 10, 20);
            System.out.println(num);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
                InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

3、反射之属性

(1)

@Test
    public void test08() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 3、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            // 4、 获取私有成员变量
            Field nameField = empClass.getDeclaredField("name");
            Field ageField = empClass.getDeclaredField("age");
            Field genderField = empClass.getDeclaredField("gender");
            // 5、设置属性可以访问权限
            nameField.setAccessible(true);
            ageField.setAccessible(true);
            genderField.setAccessible(true);
            // 6、 给属性赋值
            nameField.set(emp, "李昊哲");
            ageField.set(emp, 18);
            genderField.set(emp, 1);
            // 7、 读取属性值
            String name = (String) nameField.get(emp);
            System.out.println(name);
            Integer age = (Integer) ageField.get(emp);
            System.out.println(age);
            Integer gender = (Integer) genderField.get(emp);
            System.out.println(gender);
            // 获取所有属性
            Field[] declaredFields = empClass.getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                System.out.println(field.get(emp));
            }
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException |
                NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

(2)

@Test
    public void test09() {
        // 1、获取该类的Class对象
        Class<Emp> empClass = Emp.class;
        try {
            // 2、获取该Class对象的构造方法
            Constructor<Emp> constructor = empClass.getConstructor();
            // 3、使用该类的构造方法将该类实例化(java8+)
            Emp emp = constructor.newInstance();
            // 4、 获取私有成员变量
            Field nameField = empClass.getDeclaredField("name");
            Field genderField = empClass.getDeclaredField("gender");
            // 5、设置属性可以访问权限
            nameField.setAccessible(true);
            genderField.setAccessible(true);
            // 6、 给属性赋值
            nameField.set(emp, "李昊哲");
            genderField.set(emp, 1);
            // 7、 读取属性值
            String name = (String) nameField.get(emp);
            System.out.println(name);
            Integer gender = (Integer) genderField.get(emp);
            System.out.println(gender);
            // 获取所有属性
            Field[] declaredFields = empClass.getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                if (field.get(emp) != null ) {
                    System.out.println(field.get(emp));
                }
            }
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException |
                NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

附:反射代码演示使用的类

public class Emp {
    private String name;
    private Integer age;
    private Integer gender;

    static {
        System.out.println("我是静态代码块");
    }

    {
        System.out.println("我是构造代码块");
    }

    public Emp() {
        System.out.println("我是无参构造方法");
    }

    public Emp(String name, Integer age, Integer gender) {
        System.out.println("我是有参构造方法");
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public static void haha() {
        System.out.println("我是public static修饰的方法");
        System.out.println("仰天长啸");
    }

    public void heihei() {
        System.out.println("我是public修饰的方法");
        System.out.println("嘿嘿嘿");
    }

    private void hehe() {
        System.out.println("我是private修饰的方法");
        System.out.println("粉面含春威不露,丹唇未起笑先闻");
    }

    public Integer sum(Integer a, Integer b) {
        return a + b;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
}
举报

相关推荐

0 条评论