Thinking in Java 里关于class的理解

来源:互联网 发布:淘宝下单与发货时间 编辑:程序博客网 时间:2024/05/24 06:40

RTTI (run time type information) 允许在程序运行时使用 类型信息(type information),也就是在运行时去发现类和对象的信息。 有两种形式:一,“传统”RTTI,假设所有的类型都在编译的时候可以使用,二,发射机制,允许在运行时发现和使用类信息

原英文为:

This chapter looks at the ways that Java allows you to discover information about objects and classes at run time. This takes two forms: "traditional" RTTI, which assumes that you have all the types available at compile time, and the reflection mechanism, which allows you to discover and use class information solely at run time. 


为什么需要使用RTTI?

有如下的类继承关系:  基类 Shape ,子类 Circle Square,Triangle。 由于多态性,各个子类重新编写了draw()的方法,所有在具体调用Shape时,根据具体不同的类会实现不同的draw方法。


List<Shape> shapeList = Arrays.asList(new Circle(), new Square(), new Triangle());  for(Shape shape : shapeList)           shape.draw(); 
输出结果为: Output: Circle.draw() Square.draw() Triangle.draw() 

在这个例子中,向上转型发生在当把这些shape放入List<Shape>的时候,在转型的过程中,这些对象是Shape类的具体哪个子类也不清楚了,对于array来说他们就是shape类型。当你去取array里面的元素时,容器(实际上它把一切认为时object)自己将元素转型为shape。这是RTTI最基本的形式。因为所有的转型都在运行时验证正确性,这也是RTTI的意思:在运行时,识别一个object 的类型

在这个例子中,RTTI的转型只是部分,对象转型为Shape,而不是Circle,Square,Triangle。只是因为在这个时刻,你只知道List<Shape>里包含着Shapes.在编译的时候,将由容器和java的泛型机制来确保这一点,在运行时,由类型转换确保这一点。

接下来的事情就交给多态机制了。具体的代码执行就看shape是被引用为一个circle,square还是triangle。普遍来说,也应该是这样的,你的代码也是应该尽可能少的知道具体的类型,而只是与对象家庭的通用表示进行处理(这是是shape)。这样你的代码也会更容易去写,读,和操作。你的设计也会更容易去实现,理解,和改变。多态是面向对象的基本目标。


Class 类

去理解RTTI如何在java中工作的,先要去知道类别信息(type information)如何在运行时被表示的。这是通过一个特别的类 :Class类。Class 类包含着与类有关的信息。实际上,Class 类是用来创建所有的类的“常规”对象。

对于每个类,一个Class对象都你程序的一部分。每次你写或者编译一个新的类时,都会创建一个单独的Class对象(也被保存,也就是.class文件)。去创建类的对象时,执程程序的JVM就会去用一个叫做“类装载器”的东西。

类装载器子系统实际上是由一条链的类装载器组成,但是它只是原生类装载器。原生类装载器会载入一些“可信任”的lei,比如Java API类,通常在本地磁盘中。

所有的类都是动态载入JVM中,这取决于第一次使用这个类。当第一次调用了这个类的静态方法时,类就被载入进JVM。可以看出,构造函数其实是一个静态方法。

类装载器先去检验Class类是否被装载了,如果没有就去找.class 文件并装载。当类的字节被装载了之后,会被检验是否损坏(corrupted)且没有坏的java代码存在。

一旦某类型的Class类被载入内存中,就可以被用来创建对象了。例子见代码:

class Candy {       static { print("Loading Candy"); }}class Gum {       static { print("Loading Gum"); } }  class Cookie {       static { print("Loading Cookie"); } }public class SweetShop {       public static void main(String[] args) {             print("inside main");            new Candy();            print("After creating Candy");            try {                    Class.forName("Gum");           } catch(ClassNotFoundException e) {              print("Couldn’t find Gum");           }            print("After Class.forName(\"Gum\")");            
       new Cookie();            print("After creating Cookie");         } } 
所有的Class对象都属于Class类。获取Class对象的引用的一种方法是静态 forName()方法,返回一个Class的引用。比如 
Class.forName("Gum");
就会去装载Gum这个类,如果不存在的话。装载时,Gum的静态方法就会被执行   In the process of loading, Gum’s static clause is executed

当找不到相对应的类时,会报错ClassNotFoundException。

另外,可以通过getClass()获取Class对象,然后对其进行一些其他的操作。比如getName(),getSuperclass(),isInterface() 等等


Class literals




0 0