(1)RTTI 与class对象
RTTI是Run-Time Type Information的缩写,指运行时类型信息可以在程序运行时发现和使用。
要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的。这项工作是由称为Class对象的特殊对象完成的,它包含了与类有关的信息。类是程序的一部分,每个类都有一个Class对象。每当编写并且编译了一个新类,就会产生一个Class对象。为了生成这个类的对象,运行这个程序的JAVA虚拟机(JVM)将使用被称为类加载器的子系统。
类加载器子系统实际上可以包含一条类加载器链,但是只有一个原生类加载器,它 是JVM实现的一部分。原生类加载器加载的是所谓的可信类,包括Java API类。
Java程序在它开始运行之前并非被完全加载,其各个部分是在必需时才加载的。这一点与许多传统语言都不同。
import java.util.*;
class Initable{
static final int staticFinal=47;
static final int staticFinal2=ClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initializing Initable1");
}
}
class Initable2{
static int staticNonfinal=147;
static {
System.out.println("Initializing Initable2");
}
}
class Initable3{
static int staticNonfinal=74;
static{
System.out.println("Initialzing Initable3");
}
}
public class ClassInitialization {
public static Random rand =new Random(47);
public static void main(String[] args)throws Exception{
Class initable =Initable.class;
System.out.println("After creation Initable ref");
//Does not trigger initialization;
System.out.println(Initable.staticFinal);
//Does trigger initialization;
System.out.println(Initable.staticFinal2);
//Does trigger initialization;
System.out.println(Initable2.staticNonfinal);
Class initable3=Class.forName("typeinfo.Initable3");
//Class initable3=Class.forName("Initable");//书中该处forName的参数仅有类名,但直接运行报异常,实际该处参数应在类名前添加包名。
System.out.println("After creation Initable3 ref");
System.out.println(Initable3.staticNonfinal);
}
}
初始化有效地实现了尽可能的惰性。从对initable引用的创建中可以看到,仅使用.class语法来获得对类的引用不会引发初始化。但是,为了产生Class引用,Class.forName()立即就进行了初始化。
static final是编译期常量,获取这个值不需要对整个类初始化
static final的不是常量,而是随机数,那还是会对类进行初始化
static而不是final的,要先进行链接初始化,所以还是会对类初始化
forName("类名")返回一个Class对象的引用,主要被用作如果类没有被加载就加载它
getName()返回全限定的类名
getSimpleName()返回不含包名的类名
getCanonicalName() 返回全限定类名
getInterfaces()返回Class对象的接口们
getSuperclass()返回直接基类
newInstance()得到Object引用(实现“虚拟构造器”的一种途径,它允许你声明:“我不知道你的确切类型,但是无论如何都要争取”,newInstance()创建的类必须有默认构造器)
(2) 泛化的Class引用 新的转型语法 类型转换前先做检查
Class引用总是指向某个Class对象,表示的是它所指对象的确切类型。
使用泛型引用,可以限定class引用的类型,使其不能再指向其他类型,是的编译器强制执行额外的类型检查。普通的class引用没有这个限制。
Class<Cat> c = Cat.class;
为了放松限制,可以使用通配符,符号为“?”,表示任何类型。使用通配符产生的class引用,可以指向其它类型。
使用“?extends BaseType”,可以创建一个范围,表示该类或该类的子类。
向Class添加泛型语法的原因是为了提供编译期类型检查。
将泛型语法用于class对象,newInstance()将返回该对象的确切类型。
Class<Cat> c = Cat.class;
Cat mimi = c.newInstance();
使用 要转成类型的对象 = cast(被转对象);
Cat c= new cat();
Class<Pet> p = Pet.class;
Pet pet = p.cast(c);
这个方法很繁琐,除了极端罕见情况外几乎用不到,毕竟平时使用
Pet pet = (Pet)c;
简单一句就可以了
执行错误的类型转换,会抛出ClassCastException。
IllegalAccessException表示违反Java安全机制。
向上转型可以不显式,向下转型要显式。
inatanceof只能与命名类型(就是类名)比较,不能与对象比较。
(3) instanceof与class的等价性
instanceof 保持了类型的概念,它指的是“”你是这个类吗,或者你是这个类的派生类吗?“”而如果用==比较实际的Class对象,就没有考虑继承----它或者是这个确切的类型,或者不是。
(4) 反射:运行时的类信息
单独用一篇博客总结
(5) 动态代理
也单独用一篇博客总结。