Java面向对象之 类加载及 通过反射获取类的结构信息

1、类加载

1.1、基本说明

在这里插入图片描述

package classload_;

import reflection.Cat;

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
    }
}
1.2、类加载时机

在这里插入图片描述

1.3、类加载过程图

在这里插入图片描述

1.4、类加载各阶段完成任务

在这里插入图片描述

1.4.1、加载阶段

在这里插入图片描述

1.4.2、连接阶段-验证

在这里插入图片描述

1.4.3、连接阶段-准备

在这里插入图片描述

package classload_;

/**
 * 说明一个类加载的链接阶段-准备
 */
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.4.4、连接阶段-解析

在这里插入图片描述

1.4.5、Initialization(初始化)

在这里插入图片描述

package classload_;

/**
 * 类加载-初始化阶段
 */
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 = 10
        */

        // 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() 构造器被执行");
    }
}

2、通过反射获取类的结构信息

2.1、第一组: java.lang.Class 类

在这里插入图片描述

2.2、第二组: java.lang.reflect.Field 类

在这里插入图片描述

2.3、第三组: java.lang.reflect.Method 类

在这里插入图片描述

2.4、第四组: java.lang.reflect.Constructor 类

在这里插入图片描述

package 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;

/**
 * 通过反射获取类的结构信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    @Test
    public void api_02() throws ClassNotFoundException, NoSuchMethodException {
        // 得到Class对象
        Class<?> personCls = Class.forName("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, NoSuchMethodException {

        // 得到Class对象
        Class<?> personCls = Class.forName("reflection.Person");
        // getName: 获取全类名
        System.out.println(personCls.getName());  // 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());
        }
        // 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());  // 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;  // 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() {

    }
}

控制台输出

本类中所有属性=name 该属性的修饰符值=1 该属性的类型=class java.lang.String
本类中所有属性=age 该属性的修饰符值=12 该属性的类型=int
本类中所有属性=job 该属性的修饰符值=0 该属性的类型=class java.lang.String
本类中所有属性=sal 该属性的修饰符值=2 该属性的类型=double
本类中所有方法=m1 该方法的访问修饰符值=1 该方法返回类型void
该方法的形参类型=class java.lang.String
该方法的形参类型=int
该方法的形参类型=double
本类中所有方法=m2 该方法的访问修饰符值=4 该方法返回类型class java.lang.String
本类中所有方法=m4 该方法的访问修饰符值=2 该方法返回类型void
本类中所有方法=m3 该方法的访问修饰符值=0 该方法返回类型void
本类中所有构造器=reflection.Person
该构造器的形参类型=class java.lang.String
该构造器的形参类型=int
本类中所有构造器=reflection.Person
该构造器的形参类型=class java.lang.String
本类中所有构造器=reflection.Person

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值