java(Class 常用方法 获取Class对象六种方式 动态和静态加载 类加载流程)

news2024/11/27 6:17:49

Class

  • Class常用方法
  • 获取Class对象六种方式
  • 哪些类型有Class对象
  • 动态和静态加载
  • 类加载流程
    • 加载阶段
    • 连接阶段
      • 连接阶段-验证
      • 连接阶段-准备
      • 连接阶段-解析
    • 初始化阶段
  • 获取类结构信息


Class常用方法

第一步:创建一个实体类

public class Car {
    public String brand = "宝马";
    public int price = 500000;
    public String color = "白色";

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                ", color='" + color + '\'' +
                '}';
    }
}

第二步:常用方法的演示

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        String classAllPath = "Reflection.Car";
        //获取到Car类 对应的 Class对象
        //<?> 表示不确定的Java类型
        Class<?> cls = Class.forName(classAllPath);
        //输出cls
        System.out.println(cls); //显示cls对象,是哪个类的Class对象 class Reflection.Car
        System.out.println(cls.getClass());//输出cls运行类型 class java.lang.Class
        //得到包名
        System.out.println(cls.getPackage().getName());//包名
        //得到全类名
        System.out.println(cls.getName());
        //通过cls创建对象实例
        Car car = (Car)cls.newInstance();
        System.out.println(car);
        //通过反射获取属性 brand
        Field brand = cls.getField("brand");
        System.out.println(brand.get(car));//宝马
        //通过反射给属性赋值
        brand.set(car,"奔驰");
        System.out.println(brand.get(car));//奔驰
        //得到所有的属性(字段)
        Field[] fields = cls.getFields();
        for(Field f:fields){
            System.out.println(f.getName());//名称
        }
    }
}

运行结果:
在这里插入图片描述


获取Class对象六种方式

第一种:在已知一个类的全类名,且该类在类的路径下,可通过Class类的静态方法Class.forName()获取(多用于配置文件,读取全类路径,加载类)

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Class.forName
        String classAllPath = "Reflection.Car";//通过读取配置文件获取
        Class<?> cls1 = Class.forName(classAllPath);
    }
}

第二种:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        //2.类名.class,应用场景:用于参数传递
        Class cls2 = Car.class;
    }
}

第三种:若已知某个类的实例,调用该实例的getClass()方法获取Class对象

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        //3.对象.getClass(),应用场景:有对象实例
        Car car = new Car();
        Class cls3 = car.getClass();
    }
}

第四种:通过类加载器来获取到类的Class对象

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        //4.通过类加载器[4种]来获取到类的Class对象
        String classAllPath = "Reflection.Car";
        //(1)先得到类加载器 car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2)通过类加载器得到Class对象
        Class<?> cls4 = classLoader.loadClass(classAllPath);
    }
}

基本数据类型按如下方式得到Class类对象

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        Class<Boolean> booleanClass = boolean.class;
    }
}

基本数据类型对应的包装类,可以通过.TYPE得到Class类对象

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Integer> type1 = Integer.TYPE;
        Class<Character> type2 = Character.TYPE;
    }
}

哪些类型有Class对象

1.外部类,成员内部类,静态内部类,局部内部类,匿名内部类
2.interface:接口
3.数组
4.enum:枚举
5.annotation:注解
6.基本数据类型
7.void


动态和静态加载

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载
1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
假设我现在在代码里面放了一个没有创建的Dog类

public class ClassLoad_ {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入key");
        String key = sc.next();
        switch (key){
            case "1":
                Dog dog = new Dog();
                dog.cry();
                break;
            case "2":
                System.out.println("ok");
                break;
            default:
                System.out.println("do nothing");
        }
    }
}

导致在编译的时候就发生了报错,虽然我们在运行的时候不一定会使用到,因为new Dog()是静态加载,因此必须编写Dog
在这里插入图片描述
2.动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性

public class ClassLoad_ {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入key");
        String key = sc.next();
        switch (key){
            case "1":
                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:
                System.out.println("do nothing");
        }
    }
}

因为反射是动态加载,可以通过编译,只有在运行的时候才会报错,Person类是动态加载,所以,没有编写Person类也不会报错,只有动态加载该类的时候才会报错
在这里插入图片描述

1.当创建对象时(new) //静态加载
2.当子类被加载时,父类也加载 //静态加载
3.调用类中的静态成员时//静态加载
4.通过反射//动态加载


类加载流程

在这里插入图片描述
在这里插入图片描述

加载阶段

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.long.Class对象

连接阶段

连接阶段-验证

目的是为了确定文件中字节流包含的信息符合当前虚拟机的要求,并且不会危害安全,可以考虑使用-Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间
在这里插入图片描述

连接阶段-准备

JVM会在该阶段对静态变量,分配内存默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配(常量和静态变量不一样,因为一旦赋值就不变,它直接就是它对应的值)

连接阶段-解析

虚拟机将常量池的符号引用替换为直接引用的过程中,在编译的过程中因为没有实际的内存地址,所以只能用符号的方法来记录,当加载好之后用地址来替换

初始化阶段

到初始化阶段,才真正开始执行类中定义的java程序代码,此阶段是执行()方法过程()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并

示例代码:

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}*/
        new B(); 
        System.out.println(B.num);
    }
}
class B{
    static {
        System.out.println("B 静态代码快被执行");
        num = 300;
    }
    static int num = 100;
    public B(){
        System.out.println("B() 构造器被执行 "+num);
    }
}

运行结果:
在这里插入图片描述
如果直接使用类的静态属性,也会导致类的加载
注:
虚拟机保证一个类的()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都需要阻塞等待,直到线程执行()方法完毕


获取类结构信息

在这里插入图片描述

public class ReflectionUtils {
    public static void main(String[] args) throws ClassNotFoundException {
        api_01();
    }
    //第一组方法API
    public static void api_01() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection.com.hspedu.classload.Person");
        //获取全类名
        System.out.println(personCls.getName());
        //获取简单类名
        System.out.println(personCls.getSimpleName());
        //获取所有public修饰的属性,包含本类及父类
        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println("本类及父类属性="+field.getName());
        }
        //获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有的属性="+declaredField.getName());
        }
        //获取所有public修饰的方法,包含本类以及父类
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本类以及父类的方法="+method.getName());
        }
        //获取本类所有的方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类所有方法="+declaredMethod.getName());
        }
        //获取所有public修饰的构造器,包含本类
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本类以及父类的构造器="+ constructor.getName());
        }
        //获取本类所有的构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类所有的构造器"+declaredConstructor.getName());
        }
        //以Package形式返回包信息
        System.out.println(personCls.getPackage());
        //以Class形式返回父类信息
        System.out.println("父类的class对象"+personCls.getSuperclass());
        //以Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息="+anInterface.getName());
        }
        //返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息="+annotation);
        }
    }
}
interface IA{

}
interface IB{

}
class A{
    public String hobby;
    public void hi(){}
    public A(){}
}
@Deprecated
    class Person extends A implements IA,IB{
        public Person(){}
        public Person(String s){ }
        private Person(String name,int age){}
        //属性
        public String name;
        protected int age;
        String job;
        private double sal;
        //方法
        public void m1(){

        }
        protected void m2(){

        }
        void m3(){

        }
        private void m4(){

        }
    }

在这里插入图片描述

public class ReflectionUtils {
    public static void main(String[] args) throws ClassNotFoundException {
        api_02();
    }
    public static void api_02() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection.com.hspedu.classload.Person");
        //获取本类所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中的所有属性="+declaredField.getName()
                               +" 该属性的修饰符值="+declaredField.getModifiers()
                               +" 该属性的类型="+declaredField.getType());
        }
    }
}
interface IA{

}
interface IB{

}
class A{
    public String hobby;
    public void hi(){}
    public A(){}
}
@Deprecated
    class Person extends A implements IA,IB{
        public Person(){}
        public Person(String s){ }
        private Person(String name,int age){}
        //属性
        public String name;
        protected static int age;
        String job;
        private double sal;
        //方法
        public void m1(){

        }
        protected void m2(){

        }
        void m3(){

        }
        private void m4(){

        }
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/402737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql数据库innodb存储引擎之事务原理

事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作要求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 四大特性&#xff1a; redo log和undo log&#xff1a;一致性、原子性…

Map和Set总结

Map和Set Map和Set是专门用来进行搜索的数据结构&#xff0c;适合动态查找 模型 搜索的数据称为关键字(key)&#xff0c;关键字对应的叫值(value)&#xff0c;key-value键值对 key模型key-value模型 Map存储的就是key-value模型&#xff0c;Set只存储了key Map Map是接口类…

ES增量同步方案

1 基于业务代码嵌入式的增量同步方式在Java业务代码要修改业务数据的地方&#xff0c;增加调用写入ES数据的方法优点&#xff1a;1、实现方式简单&#xff0c;可控粒度高&#xff1b;2、不依赖第三方数据同步框架&#xff1b;3、数据库不用做特殊配置和部署&#xff1b;缺点&am…

Qt学习_10_纯Ui操作_设置窗口、菜单栏、工具栏、按钮的图标

前言 Qt项目&#xff0c;如果功能少&#xff0c;项目小&#xff0c;用代码来配置图标的方式问题不大&#xff0c;无可厚非。但是一旦项目的功能复杂内容很多&#xff0c;用代码来配置图标的方式就显得很冗余&#xff0c;能在ui设计界面完成的工作&#xff0c;尽量就在ui设计界…

人工智能实验一:使用搜索算法实现罗马尼亚问题的求解

1.任务描述 本关任务&#xff1a; 了解有信息搜索策略的算法思想&#xff1b;能够运用计算机语言实现搜索算法&#xff1b;应用A*搜索算法解决罗马尼亚问题&#xff1b; 2.相关知识 A*搜索 算法介绍 A*算法常用于 二维地图路径规划&#xff0c;算法所采用的启发式搜索可以…

66 - 进程互斥锁的应用示例

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;深入浅出操作系统 - 目录 文章目录1. 简单生产消费者问题1.1 具体问题描述1.2 解决方案1.3 简单生产消费者问题模型1.4 编程实验&#xff1a;生产消费者示例2. 多任务读写问题&a…

中国人民大学与加拿大女王大学金融硕士,让这一年有一个骄傲的句号

在中国人民大学与加拿大女王大学金融硕士项目就读的同学&#xff0c;都有一个共同的目标&#xff0c;那就是在就读的这一年能画上一个圆满的句号。当拿到毕业证书的那一刻&#xff0c;所有的付出和努力都是值得的&#xff0c;在这里学习提升各自理论知识与金融服务经验&#xf…

学生信息表

目录 一、功能说明 二、核心思想 三、所用知识回顾 四、基本框架 五、js功能实现部分 一、功能说明 &#xff08;1&#xff09;输入对应的信息&#xff0c;点击录入可以为下面的表格添加一条记录&#xff0c;注意当所填信息不完整时不允许进行提交。 &#xff08;2&…

高校如何通过校企合作/实验室建设来提高大数据人工智能学生就业质量

高校人才培养应该如何结合市场需求进行相关专业设置和就业引导&#xff0c;一直是高校就业工作的讨论热点。亘古不变的原则是&#xff0c;高校设置不能脱离市场需求太远&#xff0c;最佳的结合方式是&#xff0c;高校具有前瞻性&#xff0c;能领先市场一步&#xff0c;培养未来…

解决win10的过度保护导致文件下载不了程序不能打开运行

win7看来大概是要离我们远去了&#xff0c;虽然我们还能看见她的背影&#xff0c;但大势所趋&#xff0c;我们也只能慢慢的接受win10进入到我们的日常生活。但win10很多时候过度的保护却给我们带来了不便。这里列举两个最常见的问题&#xff0c;当然我这里也给出了解决方案。 文…

无线网络渗透测试系列学习(二) - 在VMware中搭建Metasploit靶机的详细步骤以及端口的简单了解

引言&#xff1a; 无线网络渗透测试系列学习目录&#xff1a; 无线网络渗透测试系列学习&#xff08;一&#xff09; - 在Windows系统下使用虚拟机安装Kali Linux操作系统 在上一篇文章中我们讲解了在Windows下如何在VMware虚拟机中安装Kali Linux操作系统和对Kali的简单配置…

vue项目部署到IIS

项目打包 vue 部署包&#xff1a; 项目路径运行npm run build 运行后生成一个dist文件夹&#xff0c;把这个文件夹放到要部署的服务器 IIS 配置 程序 需要用到下面这两个程序进行配置&#xff1a; 如果 IIS 没有 Web平台安装程序&#xff08;上图管理模块第二个&#x…

3月12日 植树节 Arbor Day / Planting Trees Day

"植树节“是一些国家为防止森林过度开伐&#xff0c;激发人们爱林、造林的感情而设立的法定节日。Arbor Day is one day in the year that prevents deforestation,celebrates trees and promotes planting.春天是植树的时间。Spring is the prime time for planting tree…

python3 简单爬虫入门 抓取男神图

主要目的 为 快速爬虫入门 参考&#xff1a;https://blog.csdn.net/c406495762/article/details/72597755 注意编写日期&#xff1a;2023-3-9 如果时间过久&#xff0c;则代码可能会失效&#xff0c;如果失效&#xff0c;可以根据下面的解析过程&#xff0c;手动更新代码。 …

云端Docker搭建ABY库以及本地CLion使用

文章目录ABY的搭建以及使用前言ABY库的下载、安装及测试CLion配置后续杂项项目改名使用其他的库最后ABY的搭建以及使用 前言 仅做记录&#xff0c;仅供参考&#xff0c;不同人有不同的使用方式命令手敲&#xff0c;可能有错&#xff0c;自己辨识勿问&#xff0c;我懂的也不多…

C++ Primer Plus 第6版 读书笔记(6) 第 6 章 分支语句和逻辑运算符

第 6 章 分支语句和逻辑运算符 C是在 C 语言基础上开发的一种集面向对象编程、泛型编程和过程化编程于一体的编程语言&#xff0c;是C语言的超集。本书是根据2003年的ISO/ANSI C标准编写的&#xff0c;通过大量短小精悍的程序详细而全面地阐述了 C的基本概念和技术&#xff0c;…

从 Clickhouse 到 Apache Doris,慧策电商 SaaS 高并发数据服务的改造实践

作者介绍&#xff1a; 马成&#xff0c;慧策 JAVA高级研发工程师慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算 PaaS、SaaS 模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c;实现…

C++面向对象编程之六:重载操作符(<<,>>,+,+=,==,!=,=)

重载操作符C允许我们重新定义操作符&#xff08;例如&#xff1a;&#xff0c;-&#xff0c;*&#xff0c;/&#xff09;等&#xff0c;使其对于我们自定义的类类型对象&#xff0c;也能像内置数据类型&#xff08;例如&#xff1a;int&#xff0c;float&#xff0c;double&…

Java 最小路径和

最小路径和中等给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。说明&#xff1a;每次只能向下或者向右移动一步。示例 1&#xff1a;输入&#xff1a;grid [[1,3,1],[1,5,1],[4,2,1]]输出&…

求“二维随机变量的期望E(X)与方差D(X)”例题(一)

离散型 设随机变量(X,Y)的联合分布律为 X\Y0100.10.210.30.4 (1)求E(X) 先求x的边缘分布律&#xff0c;表格里x0的概率为0.10.2&#xff0c;于是我们可得 X01P0.30.7直接求E(X)即可&#xff0c;得到结果 (2)求E(XY) 直接x与y相乘就行。 记得别乘多了&#xff0c;别的算了又…