RTTI 语法

Java 是通过 Class 对象来实现 RTTI 机制的,即使我们只是要做些诸如类型转换这类的事
情。Class 类也提供了许多其他途径,以方便我们使用 RTTI。
首 先 , 你 需 要 获 得 指 向 适 当 的 Class 对 象 的 引 用 。 一 种 办 法 是 用 字 符 串 以 及
Class.forName()方法,就象前例演示的那样。这种做法很方便,因为你在获取 Class
的引用事,并不需要生成该 Class 类型的对象。然而,如果你已经有了一个你感兴趣的类
型的对象,那么你就可以通过调用 getClass()来获取 Class 的引用,这是根类 Object
提供的方法。它返回 Class 的引用,用来表示对象的实际类型。Class 提供了一些有趣的
方法,下面的例子为你展示这些方法:
//: c10:ToyTest.java
// Testing class Class.
import com.bruceeckel.simpletest.*;
interface HasBatteries {}
interface Waterproof {}
interface Shoots {}
class Toy {
  // Comment out the following default constructor
  // to see NoSuchMethodError from (*1*)
  Toy() {} 
  Toy(int i) {}
}
class FancyToy extends Toy
implements HasBatteries, Waterproof, Shoots {
  FancyToy() { super(1); }
}
public class ToyTest {
private static Test monitor = new Test();
static void printInfo(Class cc) {
    System.out.println("Class name: " + cc.getName() +
" is interface? [" + cc.isInterface() + "]");
  } 
public static void main(String[] args) {
    Class c = null;
try {
      c = Class.forName("FancyToy");
    } catch(ClassNotFoundException e) {
      System.out.println("Can't find FancyToy");
      System.exit(1);
    } 
    printInfo(c);
    Class[] faces = c.getInterfaces();
for(int i = 0; i < faces.length; i++)
      printInfo(faces[i]);
    Class cy = c.getSuperclass();
    Object  o = null;
try {
      // Requires default constructor:
      o = cy.newInstance(); // (*1*)
    } catch(InstantiationException e) {
      System.out.println("Cannot instantiate");
      System.exit(1);
    } catch(IllegalAccessException e) {
      System.out.println("Cannot access");
      System.exit(1);
    } 
    printInfo(o.getClass());
    monitor.expect(new String[] {
"Class name: FancyToy is interface? [false]",
"Class name: HasBatteries is interface? [true]",
"Class name: Waterproof is interface? [true]",
"Class name: Shoots is interface? [true]",
"Class name: Toy is interface? [false]"
    });
  } 
} ///:~
从中可以看出,FancyToy 类相当复杂,因为它不但继承了 Toy 类,而且还实现了
HasBatteries,Waterproof 以及 Shoots 接口。在 main()方法中,通过在适当的 try
语句块中使用 forName(),创建并初始化了一个指向 FancyToy Class 的引用。


Class.getInterfaces()方法返回 Class 对象的数组,这些对象代表的是某个 Class
对象所包含的接口。


如果你有一个 Class 对象,那么你就可以通过 getSuperclass()获取它的直接基类。这
个方法自然也是返回一个 Class 的引用,所以你可以进一步查询其基类。这意味着在运行
期,你可以找到一个对象完整的类层次结构。


乍看起来,Class 的 newInstance()方法似乎只是另一种克隆 clone()对象的方法。然
而,即使原先没有任何对象存在,你也可以用 newInstance()创建一个新的对象,就像在
上例中并没有任何 Toy 对象,只有 y 的 Class 对象的引用 cy。这是一种实现“虚拟构造
器(virtual constructor)”的途径,这使得你可以说:“尽管我不知道你的准确类型
是什么,但无论怎样,还是请正确地创建你自己。”在上面的例子中,cy 只是一个 Class
的引用,在编译期并不知道更多的类型信息。当你创建一个新实例时,你将得到一个 Object
引用,但这个引用实际指向的是一个 Toy 对象。所以如果向 Object 发送它不能接收的消
息,你必须先对其进行深入了解,进行类型转换。以外,使用 newInstance()的类必须要
有一个缺省构造器。在下一节,通过使用 Java 反射 API(Java reflecion API),你
会看到如何使用任意的构造器来动态地创建对象。


最后一个要介绍的方法是 printInfo(),它以一个 Class 引用为参数,通过 getName()
获取其名字,并通过 isInterface()查看它是否是一个接口。因此,通过使用 Class 对

象,我们可以找出一个对象的任何信息。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值