位置: IT常识 - 正文

day43-反射02(反射怎么解释)

编辑:rootadmin
Java反射02 2.Class类 2.1基本介绍 Class类也是类,因此也继承Object类 Class类对象不是new出来的,而是系统创建的 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次 每个类的实例都会记得自己是由哪个Class实例所生成 通过Class对象可以得到一个类 ... Java反射022.Class类2.1基本介绍

推荐整理分享day43-反射02(反射怎么解释),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:何谓反射时,反射db,反射 go,反射 go,反射db,反射反射,反射 get,反射 go,内容如对您有帮助,希望把文章链接给更多的朋友!

Class类也是类,因此也继承Object类

Class类对象不是new出来的,而是系统创建的

对于某个类的Class类对象,在内存中只有一份,因为类只加载一次

每个类的实例都会记得自己是由哪个Class实例所生成

通过Class对象可以得到一个类的完整结构(通过一系列API)

Class对象是存放在堆的

类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括 方法代码,变量名,方法名,访问权限等)

当我们加载完类之后,除了会在堆里生成一个Class类对象,还会在方法区生成一个类的字节码二进制数据(元数据)

例子:

package li.reflection.class_;import li.reflection.Cat;//对Class类的特点的梳理public class Class01 { public static void main(String[] args) throws ClassNotFoundException { //1.Class类对象不是new出来的,而是系统创建的 //1.1.传统的 new对象 /**通过ClassLoader类中的loadClass方法: * public Class<?> loadClass(String name) throws ClassNotFoundException { * return loadClass(name, false); * } */ //Cat cat = new Cat(); //1.2反射的方式 /**在这里debug,需要先将上面的Cat cat = new Cat();注释掉,因为同一个类只加载一次,否则看不到loadClass方法 * (这里也验证了:3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次) * 仍然是通过 ClassLoader类的loadClass方法加载 Cat类的 Class对象 * public Class<?> loadClass(String name) throws ClassNotFoundException { * return loadClass(name, false); * } */ Class cls1 = Class.forName("li.reflection.Cat"); //2.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次 Class cls2 = Class.forName("li.reflection.Cat"); //这里输出的hashCode是相同的,说明cls1和cls2是同一个Class类对象 System.out.println(cls1.hashCode());//1554874502 System.out.println(cls2.hashCode());//1554874502 }}

Class类对象不是new出来的,而是系统创建的:

在Cat cat = new Cat();处打上断点,点击force step into,可以看到

注释Cat cat = new Cat();,在Class cls1 = Class.forName("li.reflection.Cat");处打上断点,可以看到 仍然是通过 ClassLoader类加载 Cat类的 Class对象

2.2Class类常用方法public static Class<?> forName(String className)//传入完整的“包.类”名称实例化Class对象public Constructor[] getContructors() //得到一个类的全部的构造方法public Field[] getDeclaredFields()//得到本类中单独定义的全部属性public Field[] getFields()//得到本类继承而来的全部属性public Method[] getMethods()//得到一个类的全部方法public Method getMethod(String name,Class..parameterType)//返回一个Method对象,并设置一个方法中的所有参数类型public Class[] getInterfaces() //得到一个类中锁实现的全部接口public String getName() //得到一个类完整的“包.类”名称public Package getPackage() //得到一个类的包public Class getSuperclass() //得到一个类的父类public Object newInstance() //根据Class定义的类实例化对象public Class<?> getComponentType() //返回表示数组类型的Classpublic boolean isArray() //判断此class是否是一个数组

应用实例

Car:

package li.reflection;public class Car { public String brand = "宝马"; public int price = 500000; public String color ="白色"; @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", price=" + price + ",\'' + '}'; }}

Class02:

package li.reflection.class_;import li.reflection.Car;import java.lang.reflect.Field;//演示Class类的常用方法public class Class02 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { String classAllPath = "li.reflection.Car"; //1.获取到 Car类 对应的 Class对象 //<?>表示不确定的Java类型 Class<?> cls = Class.forName(classAllPath); //2.输出cls System.out.println(cls);//将会显示cls对象是哪个类的Class对象 class li.reflection.Car System.out.println(cls.getClass());//输出cls的运行类型 class java.lang.Class //3.得到包名 System.out.println(cls.getPackage().getName());//li.reflection :Class对象对应的类是在哪个包下面 //4.得到全类的名称 System.out.println(cls.getName());//li.reflection.Car //5.通过cls创建一个对象实例 Car car = (Car)cls.newInstance(); System.out.println(car);//调用car.toString() //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 f:fields) { System.out.println(f.getName());//依次输出各个属性字段的名称 } }}2.3获取Class类对象的各种方式

前提:已经知道一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException

实例:Class cls1 = Class.forName("java.lang.Cat");

应用场景:多用于配置文件,读取类全路径,加载类

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

实例:Class cls2 = Cat.class;

应用场景:多用于参数传递,比如通过反射得到对应构造器对象

前提:已某个类的实例,调用该实例的getClass()方法获取Class对象

实例:Class cls3 = 对象.getClass();//运行类型

应用场景:通过创建好的对象,获取Class对象

其他方式

ClassLoader cl = 对象.getClass().getClassLoad();

Class cls4 = cl.loadClass("类的全类名");

基本数据类型byte,short,int,long,double,float,boolean.char, 按如下方式得到Class类对象

Class cls = 基本数据类型.class

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

Class cls = 包装类.TYPE

例子:

package li.reflection.class_;import li.reflection.Car;//演示得到Class对象的各种方式public class getClass_ { public static void main(String[] args) throws ClassNotFoundException { //1.Class.forName String classAllPath = "li.reflection.Car";//这里一般是通过配置文件获取全路径 Class cls1 = Class.forName(classAllPath); System.out.println(cls1);//class li.reflection.Car //2.类名.class ,多用于参数传递 Class cls2 = Car.class; System.out.println(Car.class);//class li.reflection.Car //3.对象.getClass() ,应用场景,有对象实例 Car car = new Car(); Class cls3 = car.getClass(); System.out.println(cls3);//class li.reflection.Car //4.通过类加载器(4种)来获取到类的 Class对象 //(1)先得到car对象的类加载器(每个对象都有一个类加载器) ClassLoader classLoader = car.getClass().getClassLoader(); //(2)通过类加载器得到Class对象 Class cls4 = classLoader.loadClass(classAllPath); System.out.println(cls4);//class li.reflection.Car //cls1,cls2,cls3,cls4其实是同一个Class对象 System.out.println(cls1.hashCode());//1554874502 System.out.println(cls2.hashCode());//1554874502 System.out.println(cls3.hashCode());//1554874502 System.out.println(cls4.hashCode());//1554874502 //5.基本数据类型按如下方式得到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.基本数据类型对应的8种包装类,可以通过 .TYPE得到Class类对象 Class<Integer> type1 = Integer.TYPE; Class<Character> type2 = Character.TYPE; System.out.println(type1); System.out.println(integerClass.hashCode());//1846274136 System.out.println(type1.hashCode());//1846274136 }}2.4哪些类型有Class对象外部类,成员内部类,静态内部类,局部内部类,匿名内部类interface:接口数组enum:枚举annotation:注解基本数据类型voidday43-反射02(反射怎么解释)

例子:

package li.reflection.class_;import java.io.Serializable;//演示哪些类有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;//注解 //Thread类中的枚举State--用来表示线程状态 Class<Thread.State> cls6 = Thread.State.class;//枚举 Class<Long> cls7 = long.class;//基本数据类型 Class<Void> cls8 = void.class;//void类型 Class<Class> cls9 = Class.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 }}2.5类加载

基本说明:

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载

静态加载:编译时加载相关的类,如果没有则报错,依赖性太强

静态加载的类,即使没有用到也会加载,并且进行语法的校验

动态加载:运行时加载相关的类,如果运行时不用该类,即使不存在该类,也不会报错,降低了依赖性

类加载的时机:

当创建对象时(new)//静态加载当子类被加载时 //静态加载调用类中的静态成员时 //静态加载通过反射 //动态加载

例子:静态加载和动态加载

import java.lang.reflect.*;import java.util.*;public class classLoad_ { public static void main(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: System.out.println("do nothing..."); } }}//因为new Dog()是静态加载,因此必须编写Dog//Person类是动态加载,所以即使没有编写Person类也不会报错,只有当动态加载该类时,(有问题)才会报错class Dog{ public void cry(){ System.out.println("小狗在哭泣.."); }}

在没有编写Dog类时,即使在switch选择中,不一定会运行到new dog对象的case1,但是程序仍然报错了,因为静态加载的类,即使没有用到,也会加载,并且进行语法的校验

在编写了Dog类对象后,可以看到编译通过:

运行程序:可以看到,即使没有编写Person类,但是运行时没有用到,就不会报错

使用到Person类,报错:(运行时加载)

2.6类的加载过程类加载过程图

类加载各阶段完成的任务加载阶段:将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成。连接阶段:将类的二进制数据合并到jre中初始化阶段:JVM负责对类进行初始化,这里主要是指静态成员2.6.1加载阶段

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

2.6.2连接阶段-验证

目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全包括:文件格式验证(是否以 魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证

可以考虑使用 -Xverify:none 参数关闭大部分的类验证措施,缩短虚拟机类加载的时间2.6.3连接阶段-准备

JVM会在该阶段对静态变量,分配内存并默认初始化(对应的数据类型的默认初始值,如0,0L,null,false等)。这些变量所使用的内存都将在方法区中进行分配

例如:

package li.reflection.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;}2.6.4连接阶段-解析

虚拟机将常量池内的符号引用替换为直接应用的过程

个人理解 java虚拟机中的符号引用和直接引用_maerdym的博客-CSDN博客

2.6.5初始化阶段

到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行<clinit>()方法的过程<clinit>()方法是 由编译器按语句在源文件中出现的顺序,依次自动收集类中的 所有静态变量 的赋值动作 和 静态代码块中的语句,并进行合并。-->例子1虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。

例子1:演示类加载的初始化阶段

package li.reflection.classload_;//演示类加载的初始化阶段public class ClassLoad03 { public static void main(String[] args) { //分析: /** * 1.加载B类,并生成 B的Class对象 * 2.链接 :将num默认初始化为 0 * 3.初始化阶段: * 3.1依次 自动收集类中的 所有静态变量的赋值动作 和 静态代码块中的语句,并合并 * 收集: * clinit(){ * System.out.println("B的静态代码块被执行"); * num = 300; * num = 100; * } * 合并:num =100; */ //直接使用类的静态属性也会导致类的加载 System.out.println(B.num);//100 }}class B { static { System.out.println("B的静态代码块被执行"); num = 300; } static int num = 100; public B() { System.out.println("B的构造器被执行"); }}

例子2:

在例子1中的程序里创建一个B类对象,打上断点,debug源码:

可以看到在底层中,使用了对象锁synchronized (getClassLoadingLock(name)) :

也就是说,加载类的时候,是有类的同步控制机制。

正因为有这个机制,才能保证某个类在内存中,只有一份Class对象。

本文链接地址:https://www.jiuchutong.com/zhishi/310597.html 转载请保留说明!

上一篇:Testing Applications with WebTest¶

下一篇:微擎框架破解版v2.7.25去授权一键安装纯净商业版(微擎纯净框架,无任何限制)-电脑学习网(微擎框架是开源的吗)

  • 网络推广内功秘籍:掌握网络推广3大要素(100种网络推广方法)

    网络推广内功秘籍:掌握网络推广3大要素(100种网络推广方法)

  • 电动牙刷怎么用的教程(电动牙刷怎么用)(电动牙刷怎么用视频 示范)

    电动牙刷怎么用的教程(电动牙刷怎么用)(电动牙刷怎么用视频 示范)

  • 苹果13mini怎么显示电池百分比(苹果13mini怎么显示实时网速)

    苹果13mini怎么显示电池百分比(苹果13mini怎么显示实时网速)

  • 华为p40pro是多少倍变焦的(华为p40pro是多少寸的手机)

    华为p40pro是多少倍变焦的(华为p40pro是多少寸的手机)

  • 华为p40自带微信视频带美颜吗(华为p40自带微信美颜吗)

    华为p40自带微信视频带美颜吗(华为p40自带微信美颜吗)

  • 苹果x旁白怎么关闭(苹果x旁白怎么关闭按键说明)

    苹果x旁白怎么关闭(苹果x旁白怎么关闭按键说明)

  • 支付宝如何解除拉黑好友(支付宝如何解除闲鱼绑定)

    支付宝如何解除拉黑好友(支付宝如何解除闲鱼绑定)

  • 苹果可以更新13.4.1系统吗(苹果可以更新16.5吗)

    苹果可以更新13.4.1系统吗(苹果可以更新16.5吗)

  • 华为mate20能读取u盘吗(华为mate20读取移动硬盘)

    华为mate20能读取u盘吗(华为mate20读取移动硬盘)

  • 视频怎么以文件形式发送给QQ好友(视频怎么以文件形式发送微信)

    视频怎么以文件形式发送给QQ好友(视频怎么以文件形式发送微信)

  • iphone7基带坏的前兆(iphone7基带坏了还能用wifi吗)

    iphone7基带坏的前兆(iphone7基带坏了还能用wifi吗)

  • 芒果tv超前点播怎么弄(芒果tv超前点播怎么免费观看)

    芒果tv超前点播怎么弄(芒果tv超前点播怎么免费观看)

  • 苹果xr左上角时间显示蓝色

    苹果xr左上角时间显示蓝色

  • 快手点亮为什么不显示(快手点亮为什么是红色的)

    快手点亮为什么不显示(快手点亮为什么是红色的)

  • 华为畅享9plus怎么设置返回键(华为畅享9plus怎么恢复出厂设置)

    华为畅享9plus怎么设置返回键(华为畅享9plus怎么恢复出厂设置)

  • 引入操作系统的主要目的是(引入操作系统的方法)

    引入操作系统的主要目的是(引入操作系统的方法)

  • 淘宝单张券已领取上限怎么办(淘宝单张券领取上限)

    淘宝单张券已领取上限怎么办(淘宝单张券领取上限)

  • 闲鱼多久收货不会被冻结(闲鱼多久不收货会被自动确认)

    闲鱼多久收货不会被冻结(闲鱼多久不收货会被自动确认)

  • 隔空传送正在等待是什么意思(隔空传送显示正在转换是什么)

    隔空传送正在等待是什么意思(隔空传送显示正在转换是什么)

  • 怎样才能知道对方在视频聊天(怎样才能知道对方微信和谁聊天)

    怎样才能知道对方在视频聊天(怎样才能知道对方微信和谁聊天)

  • 华为负一页怎么设置(华为负一页怎么显示火车票)

    华为负一页怎么设置(华为负一页怎么显示火车票)

  • 注册qq的邀请码怎么弄(注册qq的邀请码怎么填)

    注册qq的邀请码怎么弄(注册qq的邀请码怎么填)

  • 小米9pro怎么批量删除联系人(小米9pro怎么一键换机)

    小米9pro怎么批量删除联系人(小米9pro怎么一键换机)

  • oppo手机怎么设置定位(oppo手机怎么设置锁屏)

    oppo手机怎么设置定位(oppo手机怎么设置锁屏)

  • word怎么手动添加目录(word怎么手动添加目录虚线)

    word怎么手动添加目录(word怎么手动添加目录虚线)

  • 15分钟的视频怎么发给微信好友(15分钟的视频怎么剪辑)

    15分钟的视频怎么发给微信好友(15分钟的视频怎么剪辑)

  • 为什么爱追剧打开不了(为什么追剧的大部分是女生)

    为什么爱追剧打开不了(为什么追剧的大部分是女生)

  • 小米手机微信扫一扫不能用怎么办(小米手机微信扫码模糊)

    小米手机微信扫一扫不能用怎么办(小米手机微信扫码模糊)

  • 苹果8p黑屏中间转圈(苹果8p黑屏有一条线然后重启)

    苹果8p黑屏中间转圈(苹果8p黑屏有一条线然后重启)

  • 天猫国际如何找人代付(天猫国际从淘宝哪里找)

    天猫国际如何找人代付(天猫国际从淘宝哪里找)

  • Vue3 中 导航守卫 的使用(vue-router导航守卫)

    Vue3 中 导航守卫 的使用(vue-router导航守卫)

  • 城镇垃圾处理费的计税依据
  • 什么负债计税基础为零
  • 缴纳印花税的会计凭证
  • 缴纳上月附加税会计科目
  • 退货开具红字发票销项税为负数税务局会查吗
  • 执行企业会计准则第21号租赁的企业
  • 转登小规模以前的留抵税额能申请退吗
  • 结汇收益怎么算
  • 固定资产盘盈盘亏的会计科目
  • 已结转的凭证可以取消结转吗
  • 收到其他银行划回的款项属于什么科目
  • 非营利组织对外捐赠
  • 借款合同印花税减免优惠政策
  • 营改增后建筑公司自建行为所得税
  • 朋友借资质汇款到公司要收税吗?
  • 小规模纳税季度申报
  • 差旅费住宿专票可以抵扣增值税吗
  • 往来科目明细表
  • 开票信息银行账号有一个横杠
  • 企业所得税为15%的企业
  • 因腐败因素形成的损失企业所得税如何处理?
  • 苹果14promax价格
  • 劳务费和服务费税率一样吗
  • uniqpp
  • win7系统怎么设置最佳性能
  • dcom进程
  • 红字发票负数要怎么抵掉
  • vue-router
  • 新能源产业发展历程
  • 可以享受企业所得税加计扣除的有
  • 布莱顿小镇介绍
  • 其他收益如何核算成本
  • d3.js下载
  • 拦截器拦截html
  • 长期股权投资权益法转成本法
  • python打开文本文档中文读不出来
  • 增值税发票已经认证了,但是税票原票没给,会有什么后果
  • 钱进公账怎么转账给别人
  • 个人代人开普票要交几个点税
  • mysql内存使用详解
  • python apriori算法
  • 网上如何增加办税人员
  • 购货销售折让会计分录
  • 个体工商户税收标准2023年
  • 验证vip
  • 装修款收不回怎么办
  • 收到厂家返利如何计算成本
  • 总公司账务处理
  • 销售折扣与折让在财务报表哪里
  • 培训学校的主营业务是什么
  • 建设单位支付给施工单位的民工工资
  • 购车买的保险分别是什么
  • 新会计准则贷款计提贷款减值准备的比例
  • 纯外贸企业进项税怎么抵扣
  • 入库单金额写错可以改吗
  • 财务费用贷方余额怎么结转本年利润
  • 建筑企业其他应付款包含什么内容
  • 小规模纳税人能开专票吗2023
  • 通信费抬头为个人
  • 个体户利润总额是4万应缴纳多少个人经营所得
  • 跨月普票作废怎么处理操作步骤
  • 销售折让的会计分录
  • sqlserver数据库怎么导出
  • win8磁盘占用率高怎么处理
  • win8.1的开始菜单在哪
  • windows7显示桌面的操作方法
  • win8.1系统安装教程
  • cocos2dx官方教程
  • OnApplicationFocus
  • android调用相机闪退
  • node.js express koa
  • js基础知识
  • 数字图像处理软件idl和matlab有什么异同点
  • 境外所得税额扣除的计算
  • 2020年军人自主择业条件
  • 精准扶贫就业补贴怎么领?
  • 乌鲁木齐市公立幼儿园有哪些
  • 个人工资所得税缴纳标准2023年
  • 海淀九所税务局电话
  • 2021年税务高雅春联带横批
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设