Type information

 (本文参考了 Thinking in java中的type information这章)


  • 什么是Type information

Type指一个对象的种类,某种自定义的class,某个interface或string等,都是type的一种。

而type information即是指关于这个对象的信息。例如后面会提到,Class.forName()将返回class的名称,就是所谓的type information之一。


在两个阶段可以得知一个对象的类型:

1, 在编译阶段就已经可以得到所有的type。 例如,定义的一个String对象,在编译阶段就可得知该对象是一个String。

2, 另外一种反射机制,它允许你在运行时发现和使用对象的类型信息,即type information.


而RTTI(runtime type information)就指在运行时,获得type information的机制。

大家熟知的多态,就是RTTI的一种典型情况。而在后面的内容中我们慢慢的就能知道,可以利用runtime type information做些什么有趣的事情。

现阶段我们只需要知道利用RTTI我们可以build more powerful program(现在听起来很虚是吧~~)


  • RTTI的意义:

一个简单的例子,一个基类 Shape和它的三个子类:三角形,圆形和方形。

public class Shapes {
public static void main(String[] args) {
List<Shape> shapeList = Arrays.asList(
new Circle(), new Square(), new Triangle()
);
for(Shape shape : shapeList)
shape.draw();
}
}

从上例可以看出,这些子类的实例被放入了List<Shape>中。此时the upcast occurs when the shape is placed into the List<Shape>. During the upcast to Shape, the fact that the objects are specific types of Shape is lost. To the array, they are just Shapes.

当你从List<Shape>中将每个形状取出并draw()时,就使用了典型的RTTI。因为所有的对象从List中取出时,这些对象被自动从基类shape转换成了具体的形状,并执行特定形状的draw()。而这正是RTTI的意义所在:在运行时,一个对象的type被确认。这是实现多态的基础。


  • type information 在runtime是如何被表示的。

要理解RTTI在java中是如何工作的,你必须先知道type information在run time是如何被表示的。

我们知道一个类有两种成员变量:用static修饰的变量,被称为类变量或静态变量。静态变量是属于类本身的。没有被static修饰的变量是实例变量,是属于一个具体的类实例的。

因此我们可以得出这样一个结论:一个类在JVM中应该被表现成两部分:类本身,以及类的实例。

事实也是如此:在JVM中,一个类有两个部分:

1,表现这个类本身的对象Class

2,以及这个类的诸多实例对象。


在java中,有一个特殊的类,叫Class类。在一个类第一次被使用时(我们在后面解释什么叫“被使用时”),JVM中产生了两个东西:首先创建一个代表类本身的对象,这个对象是Class类的实例。接着创建类的实例。

而这个Class类的实例,就存储了这个类的type infomation。

注意在JVM中,一个类只会有一个Class类的实例与之对应,但是可以有任意多个类的实例。也就是说,你可以实例化一个类任意多次,但是在JVM中对应的Class类的实例只会被创建一个。

再换句话说:一个类的任意多个实例是共享一个Class类实例的。这非常合理,因为一个类的实例再多,但是属于类本身的信息有一份就够了。


1,Class对象是怎么产生的

 That is, each time you write and compile a new class, a single Class object is also created (and stored, appropriately enough, in an identically named .class file).

.class文件(即jar文件)在运行时,会被JVM中的一个重要组件:class loader装载并创建出对应的Class object。


2,Class object如何工作

所有的类都是在第一次被调用时,动态的被load到JVM的. 所谓的“第一次被调用”,就是类中的静态成员被调用。而构造函数也是类的静态方法,因此load在以下情况发生:

1,类的static成员变量或方法被调用时。

2,或new一个类时。

因此,一个java程序并不是在运行前被完全load到JVM中,而且分多次,一小段一小段的load。这导致了和c++这种statically loaded 语言在行为上的不同。

Once the Class object for that type is in memory, it is used to create all objects of that type。

上句意思是:一旦一个类的Class object在内存中了,它就会被用来创建所有该类的对象。非常合理,因为如果一个类对应的Class对象已经在JVM存在了,且我们仅需要一份,那么就不需要再创建了。


3,如何使用Class object。

要使用type information,我们必须先得到一个Class类实例的引用,然后使用这个类提供的方法,得到我们想要的information:

Anytime you want to use type information at run time, you must first get a reference to the appropriate Class object.


Class.forName()可以返回一个类对应的Class对象:Returns the Class object associated with the class or interface with the given string name.

例如,class.forName("TestClass"); 就返回了TestClass这个类对应的那个Class类实例,也就是代表了TestClass这个类的type information的那个对象。

还有一种方法就是使用Class literals:

类名+.class就是class literral。

我常常在代码中看到的,log4j就会使用:

private final static Logger LOGGER = Logger.getLogger(ClassName.class);

但是使用.class并不会导致立即实例化对应的class。


得到了引用后,我们想获得任何关于类的type information就非常简单了:其实就是使用Class这个类提供的方法。

打开java.lang.Class的java doc,浏览一遍这个类提供的所有方法,心里就有数了。下面以最常用的几个方法举例。

getName()得到当前的这个类的名字。

其他有用的方法:

getClass():继承于Object的Returns the runtime class of an object.  其实返回的就是一个Class的实例。

Class.islnstance( ): Determines if the specified Object is assignment-compatible with the object represented by thisClass.

instanceof。

getClassLoader()可以知道这个类是被哪个class loader load到JVM的。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值