java基础(12)----类型信息



(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) 动态代理

也单独用一篇博客总结。

猜你喜欢

转载自blog.csdn.net/qq_40182703/article/details/80511595