欢迎光临
我们一直在努力

TIJ阅读笔记(第十章)-JSP教程,Java技巧及代码

建站超值云服务器,限时71元/月

10:检测类型  运行时类型识别(run-time type identification,缩写为rtti)。

为什么会需要rtti  collection是一种工具,它只有一种用途,就是要为你保管其它对象。因此出于通用性的考虑,这些collection应该能持有任何东西。所以它们持有object。    class对象    想要知道java的rtti是如何工作的,你就必须首先知道程序运行的时候,类型信息是怎样表示的。这是由一种特殊的,保存类的信息的,叫做“class对象(class object)”的对象来完成。实际上类的“常规”对象是由class对象创建的。    程序里的每个类都要有一个class对象。也就是说,每次你撰写并且编译了一个新的类的时候,你就创建了一个新的class对象(而且可以这么说,这个对象会存储在同名的.class文件里)。程序运行时,当你需要创建一个那种类的对象的时候,jvm会检查它是否装载了那个class对象。如果没有,jvm就会去找那个.class文件,然后装载。由此也可知道,java程序在启动的时候并没有完全装载,这点同许多传统语言是不一样的。        class.forname("一个类的名字");    这是一个class的static方法(所有的class对象所共有的)。class对象同其它对象一样,也可以用reference来操控(这是装载器要干的),而要想获取其reference, forname()就是一个办法。它要一个表示这个类的名字的string作参数(一定要注意拼写喝大小写!)。这个方法会返回class的reference,还有一个副作用,看看这个string所说的那个类装载了没有,要是还没有那就马上装载。如果class.forname()没有找到它要装载的类,就会抛出一个classnotfoundexception。        class常数    java还提供了一种获取class对象的reference的方法:“class常数(class literal)”。      类的名字.class;    这种写法不但更简单,而且也更安全,因为它是在编译时做检查的。此外由于没有方法调用,它的执行效率也更高一些。        class常数不但能用于普通类,也可以用于接口,数组和primitive类型。此外,每种primitive的wrapper类还有一个标准的,名为type的数据成员。这个type能返回“与这种primitive相关联的wrapper类”的class对象的reference,就像这样:             … 等同于 …    boolean.class    boolean.type    char.class       character.type    byte.class       byte.type    short.class      short.type    int.class        integer.type    long.class       long.type    float.class      float.type    double.class     double.type    void.class       void.type        我喜欢尽量使用“.class”,因为这种写法与普通类的保持一致。    转换之前先作检查    到目前为止,你看到的rtti的形式有:      1。经典的类型转换:如“(shape)”,这种转换要经过rtti的检查。要是做了错误的转换,它就会抛出classcastexception。      2.代表对象类型的class对象。你可以在运行的时候查询class对象,以此来获取所需的信息。        如果不进行明确的类型转换的话,编译器时不会让你把对象赋给派生类的reference的。    java里面还有第三种rtti的形式。这就是instanceof关键词,它会告诉你对象是不是某个类的实例。它返回的是一个boolean值。    使用类常数    动态的instanceof    isinstance()能完全替代instanceof。    instanceof vs. class的相等性

rtti的语法    class.getinterfaces()方法会返回一个class对象的数组。数组中的对象分别表示它所实现的接口。  如果你手上有一个class对象,你还能用getsuperclass()问出它最近的那个父类。当然,这会返回一个class的reference,于是你可以接着问,程序运行的时候,你能以此发现对象的完整的关系。  class的newinstance()方法就像是另一种clone()对象的方法。但是,你却可以用newinstance()凭空创建出一个新的对象。  printinfo()方法,它拿一个class对象的reference作参数,用getname()提取类的名字,用isinterface()判断它是不是接口。这样,你就能仅凭class对象就找出所有你想知道的这个对象的信息了。

reflection:运行时的类信息  java以javabeans的形式提供了基于组件的编程的支持。  通过网络在远程机器上创建对象并运行程序。这被成为“远程方法调用(remote method invocation缩写是rmi)”。它能让一个java程序将对象分布到很多机器上。  除了class类,还有一个类库,java.lang.reflect也支持reflection。这个类库里面有field,method,和constructor类(它们都实现了member接口)运行时,jvm会创建一些这种类的对象来代表未知类的各个成员。然后,你就能用constructor来创建新的对象,用get()和set()来读取和修改与field队形爱女嘎相关联的成员数据,用invoke()方法调用与method对象相关联的方法了。此外,你还能用getfields(),getmethods(),getconstructors()之类的方法,获取表示成员数据,方法或构造函数的对象数组。由此,即便编译时什么信息都得不到,你也有办法能在运行时问出匿名对象的全部类型信息了。  有一点很重要,reflection不是什么妖术。当你用reflection与未知类的对象打交道的时候,jvm(会和普通的rtti一样)先看看这个对象是属于那个具体类型的,但是此后,它还是得先装载class对象才能工作。也就是,不管是从本地还是从网络,反正jvm必须拿到那个.class文件。所以rtti同reflection的真正区别在于,rtti是在编译时让编译器打开并且检查.class文件。换句话说,你是在通过“正常”途径调用对象的方法。而对reflection来说,编译时是得不到.class文件的;所以它是在运行时打开并检查那个文件。    一个提取类的方法的程序    一般来说,你不太会直接使用reflection;java之所以要有这种功能是要用它来支持一些憋的特性,比如对象的序列化和javabeans。不过在有些情况下,能动态提取类的信息还是很有用的。    class的getmethods()和getconstructors()方法分别会返回一个method和一个constructor数组。这两个类又包括一些“能把它们所代表的方法的名字,参数,返回值全部拆解开来”的方法。不过你也可以像这里所作的,只用tostring()去获取一个包括这个方法的全部特征签名的string。剩下的代码就是用来抽取命令行信息,以及判断方法特征是否与你输入的字符串相匹配(用indexof()),并且把匹配的方法列出来的。

总结:  rtti能让你用一个匿名的基类reference来获取对象的确切类型的信息。在不懂多台方法调用的时候,这么作是理所当然的,因此新手们会自然而然的想到它,于是就用错了地方,对很多从面向过程的编程语言转过来的人来说,刚开始的时候,它们还不习惯扔掉switch语句。于是当他们用rtti来编程的时候,就会错过多态性所带来的编程和代码维护方面的好处。java的本义是让你在程序里面全程使用多态性,知识在万不得已的情况下才使用rtti。  但是要想正确地使用多台方法调用,你就必须要能控制基类的定义,因为当你扩展程序的时候,可能会发现基类里面没有你想要的方法。如果这个基类是来自类库的,或是由别人控制的,那么rtti就成解决方案了:你可以继承一个新的类,然后加上你自己的方法。在程序的其他地方,你可以检测出这个类型,调用那些特殊的方法。这样做不会破坏多态性,也不影响程序的扩展性,因为加一个新的类型不会要你去到处修改switch语句。但是,如果是在程序的主体部分加入要使用新特性的嗲马的话,你就必须使用rtti来检查对象的确切类型了。  rtti还会被用来解决效率问题。假设你写了一个很好的多台程序,但是运行的时候发现,有个对象反映奇慢。于是,你就可以用rtti把则个对象捡出来,然后专门针对它的问题写代码以提高程序的运行效率,不过编程的时候切忌去过早有话代码。这是一个很有诱惑的陷阱。最好还是先让程序跑起来,然后再判断一下它跑得是不是够快了。只有觉得它还不够快,你才应该去着手解决效率问题--用profiler。

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » TIJ阅读笔记(第十章)-JSP教程,Java技巧及代码
分享到: 更多 (0)