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