Java注解与反射系列——Class类day1-3

news/2024/5/19 3:31:13 标签: java, 开发语言, 注解, 反射

Java注解反射系列——Class类

  • Class类
    • 常用方法
    • 哪些类型有Class对象?
    • 类的加载过程
      • 类的加载
      • 链接
      • 初始化
    • 什么时候会发送类的初始化
      • 类的主动引用
      • 类的被动引用
    • 获取Class实例
      • 结果
    • 类加载器的作用
      • 类缓存
      • Java中的类加载器
      • 获取类的加载器
    • 获取类中的信息

Class类

对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为具保首一个不变的Class类型的对象,一个Class对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[)的有关信息

  • Class本身也是一个类
  • Class对象只能由系统建立对象
  • 一个加载的类在JVM中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件》
  • 每个类的实例都会记得自己是由哪个Class 实例所生成
  • 通过Class可以完整地得到一个类中的所有被加载的结构
  • Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象

常用方法

方法说明
static ClassforName(String name)返回指定类名name的Class对象
Object newInstance()调用缺省构造函数,返回Class对象的一个实例
getName()返回此Class对象所表示的实体(类,接口,数组类或void)的名称。
Class getSuperClass()返回当前Class对象的父类的Class对象
Class[] getinterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Constructor[]getConstructors()返回一个包含某些Constructor对象的数组
Method getMothed(String name,Class… T)返回一个Method对象,此对象的形参类型为paramType
Field[]getDeclaredFields()返回Field对象的一个数组

哪些类型有Class对象?

  1. class
  2. interface
  3. array
  4. enum
  5. annotation
  6. primitive type
  7. void

这里大家应该都认识吧

类的加载过程

  1. 类的加载
  2. 类的链接
  3. 类的初始化

类的加载

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构然后生成一个代表这个类的java.lang.Class对象

链接

将Java类的二进制代码合并到JVM的运行状态之中的过程。
步骤如下

  • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
  • 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
  • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

初始化

执行类构造器< clinit >()方法的过程。类构造器< clinit >()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。

当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。虚拟机会保证一个类的< clinit >()方法在多线程环境中被正确加锁和同步。

什么时候会发送类的初始化

类的主动引用

一定会发生类的初始化

  1. 当虚拟机启动,先初始化main方法所在的类
  2. new一个类的对象
  3. 调用类的静态成员(除了final常量)和静态方法
  4. 使用java.lang.reflect包的方法对类进行反射调用
  5. 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类

类的被动引用

不会发生类的初始化

  1. 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
  2. 通过数组定义类引用,不会触发此类的初始化
  3. 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)

获取Class实例

java">package example.reflect;

import example.reflect.entity.Stu;

public class GetClassDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        //最推荐使用
        Class<Stu> stuClass = Stu.class;
        //方法二
        Class stu = Class.forName("example.reflect.entity.Stu");
        //方法三
        Stu stu1 = new Stu();
        Class<? extends Stu> aClass = stu1.getClass();


        System.out.println(aClass);
        System.out.println(stuClass);
        System.out.println(stu);
    }
}

结果

在这里插入图片描述

类加载器的作用

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

类加载器就是用来把class装载进内存的

类缓存

标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象

Java中的类加载器

  1. 引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库。该加载器无法直接获取
  2. 扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库
  3. 系统类加载器:负责java-classpath或-D java.class.path所指的目录下的类与jar包装入工作,是最常用的加载器

在这里插入图片描述

获取类的加载器

java">package example.reflect;

public class GetClassLoader {
    public static void main(String[] args) {
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类的加载器的父类的加载器,即获取扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
        
        //获取根加载器
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

    }
}

在这里插入图片描述

用户自定义的类都是在AppClassLoader里的
系统即JDK内置类都是在系统类加载器中的

获取类中的信息

java">package example.reflect;

import example.reflect.entity.Stu;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;

public class GetClassInfo {
    public static void main(String[] args) throws NoSuchMethodException {
        Class<Stu> stuClass = Stu.class;

        ClassLoader classLoader = stuClass.getClassLoader();
        String name = stuClass.getName();
        String simpleName = stuClass.getSimpleName();
        Package aPackage = stuClass.getPackage();
        String packageName = stuClass.getPackageName();
        Field[] fields = stuClass.getFields();
        Field[] declaredFields = stuClass.getDeclaredFields();
        Method[] methods = stuClass.getMethods();
        //获取单个指定方法,需要指定名称+参数
        Method setAge = stuClass.getMethod("setAge", int.class);
        Constructor<?>[] declaredConstructors = stuClass.getDeclaredConstructors();

        HashMap<String, Object> map = new HashMap<>();
        map.put("类加载器", classLoader);
        map.put("类名", name);
        map.put("简单类名", simpleName);
        map.put("包", aPackage);
        map.put("包名", packageName);
        map.put("属性(仅public)", fields);
        map.put("属性(所有)", declaredFields);
        map.put("本类及父类所有方法",methods);
        map.put("setAge方法",setAge);

        map.forEach((x, y) -> {
            System.out.println(x + ":" + y);
        });

        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("----------------------");
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("======================");
        for (Method method : methods) {

            System.out.println(method);
        }
        System.out.println("-=-=-==-=-=-=-=-=-=--=-");
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }
}

在这里插入图片描述


http://www.niftyadmin.cn/n/1717346.html

相关文章

Java注解与反射系列——反射示例day2-1

Java注解与反射系列——反射示例反射示例获取反射对象源码通过反射机制动态创建对象通过反射调用方法通过反射设置属性通过反射获取泛型反射操作注解&#xff08;重要&#xff09;反射示例 获取反射对象 package example.reflect;public class demo1 {public static void mai…

Java注解与反射系列——注解与反射实例day2-2

Java注解与反射系列——注解与反射实例实例CheckMethod注解Stu类测试实例 用于获取所有带有注解的方法的方法名并记录日到txt中 CheckMethod注解 package example.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java…

linux服务器管理——高可用电商项目系统部署方案

linux服务器管理——高可用电商项目系统部署方案高可用电商项目系统部署方案报告前言[摘 要][关键词]环境拓扑图完整拓扑图准备工作必要安装和操作克隆搭建LVS的DR模式简单拓扑配置IProuter查看网卡的uuid以及mac地址配置静态IP测试连通router启动路由转发查看路由表lvs1lvs2RS…

Java接口详解

Java接口什么是Java接口接口特性接口与类的区别接口特性抽象类和接口的区别如何定义接口接口的进化jdk7jdk8jdk9接口实现接口示例抽象方法1.创建接口2.书写要实现的方法3.构建实现类4.实现类5.实现方法静态常量默认方法覆盖实现静态方法私有方法普通私有方法静态私有方法接口的…

Java8时间与日期API(别再使用Date和Calendar了)

Java8时间与日期APIAPI设计原因时间日期常用类概述创建方法&#xff08;now&#xff09;生成自定义的日期时间对象&#xff08;of&#xff09;为LocalDateTime添加时区信息ZoneId类获取系统时区获取其他时区的时间关于Month枚举根据现有时间进行时间推断&#xff08;plus&#…

SpringSecurity系列——概述day1-1

SpringSecurity系列——概述简介什么是授权什么是认证quickstart1.创建项目选择依赖SpringSecurity依赖2.Controller测试3.访问localhost8080/demo用户名和密码4.登录5.退出登录简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安…

SpringSecurity系列——JWT(jjwt)day1-2

SpringSecurity系列——JWTday1-2简介官网地址Session对比JWTsession问题JWTJWT的优点JWT的结构HeaderPayloadSignatureJJWT地址JJWT基础使用和介绍导入依赖quickstart代码解释设置使用加密算法构建jwt设置payload中包含的用户信息设置加密算法压缩生成token令牌错误一&#xf…

SpringSecurity系列——简单自定义登录流程day1-3

SpringSecurity系列——简单自定义登录流程SpringSecurity认证前后端分离的登录校验流程前后端分离请求响应流程SpringSecurity完整流程如何查看过滤器1.启动类中添加逻辑进行debug2.打开评估输入表达式修改流程登录校验自定义登录流程1.导入依赖2.编写yaml3.编写entity&#x…