类型信息入门

本文深入探讨Java中的反射机制及运行时类型识别(RTTI)。解释了类加载过程,包括Class对象的生成和使用,以及Class.forName()与类字面量的不同之处。同时,文章还介绍了泛型Class引用的概念及其应用场景。
摘要由CSDN通过智能技术生成
jvm使用ClassLoader将字节码文件(class文件)加载到方法区内存中:
Class c = ClassLoader.getSystemClassLoader().loadClass("com.mypackage.MyClass");关于ClassLoader会有一篇文章来详细介绍的。
可见ClassLoader根据类的完全限定名加载类并返回了一个Class对象,而java反射的所有起源都是从这个class类开始的

a,首先来了解RTTI:  
RTTI(Run-Time Type Identification,通过运行时类型识别)的含义就是 在运行时识别一个对象的类型
也就是说,使用RTTI,可以查询父类对象的引用所指向的对象的确切类型,然后可以选择或者剔除特例。

b:了解类型信息在运行时如何表示:
类是Class类的对象,就像之前说的,在java中,处处都是对象。一个类文件就是Class类的对象,其对应的类是Class对象,每个java里面的类都对应一个Class对象(在编写并且编译后),这个对象被保存在这个类的同名class文件里。
当程序创建第一个对类的静态成员的引用时,就会加载这个类。-。构造器也是类的静态方法,即使没加static。所以很好理解类初始化器和构造器某些方面都可以初始化成员变量

c: 类加载的两种机制(都是生成对class对象的引用):Class.forName(); 还有一种的是 Class.class两种方式。
Class.forName()的机制是取得Class对象的引用的一种方法。它是用一个包含目标类的文本名的String作输入参数,返回的是一个Class对象的引用。如果没有该类需要报出异常



Class.forName()类加载的时候会初始化类中的静态方法

另一种方式生成对Class对象的引用,即使用类字面常量。这样做不仅更加简单安全,因为在编译的时候也会受到检查。更加高效。推荐使用'.class'的形式。
int.class = Integer.type;
--> .class走了三个步骤(加载, 链接, 初始化)
1,加载 ->类加载器执行的类加载,查找字节码,从字节码中创建一个Class对象
2, 链接 -> 将验证类中的字节码, 为静态域分配空间,如果有必要的话,也将解析这个列创建的对其他类的引用。
3, 初始化 如果该类具有超类,则对其初始化,执行静态初始化类和静态初始化块

.class 是尽可能的"惰性"。不会加载这个初始化静态类。

对于.class(A)和Class.forName()(B)加载生成的对象,追查分析是。A没有初始化加载了reflectionData 这个属性。而B初始化加载了。关于 ReflectionData可点击这里 ReflectionData属性详解.note .

d: 泛化的Class引用
Class引用表示的就是它所指向的对象的确切类型, 而该对象便是Class类的一个对象。泛化的作用就是将它的类型变得更具体了。
1 :现在有一下三种形式
Class intClass = Integer. class ;
Class<Integer> myIntClass = Integer. class ;
Class<?> youIntClass = Integer. class ;
第一种是不推荐使用这种类型的 第二种是编译器强制执行额外的类型检查 第三种是第一种的扩展通配符“?”仅仅是为了说明你是故意使用一个非具体累的引用而不是疏忽。
2: 并且Class类中同样支持通配符和extends关键字相结合或者和Super类相结合
其中RedToy是Toy的子类
Class<RedToy> redToyClass = RedToy. class ;
Class<? super RedToy> superClass = redToyClass.getSuperclass();
try {
Toy toy = (Toy) superClass.newInstance();
toy.writes();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
super这个扩展字段虽然有了限制 但是子类的方法父类不一定会有,所以转换以后不能直接调用父类中的方法。和extends不一样

RTTI和反射的真正区别是:对RTTI来说,编译器在编译的时候打开和检查.class文件。而对于反射来说,.class文件在编译过程中是不可获取的,是在运行中打开和检查.class文件


Constructor<T> person = type.getConstructor( int . class );
Person person = person.newInstance (1);





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值