当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:17:00  来源:本站整理

rtti在java造型前的查抄[Java编程]

赞助商链接



  本文“rtti在java造型前的查抄[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
迄今为止,我们已知的RTTI情势包含:
(1) 经典造型,如"(Shape)",它用RTTI确保造型的精确性,并在碰到一个失利的造型后产生一个ClassCastException违例.
(2) 代表对象范例的Class对象.可查询Class对象,获得有效的运行期资料.

在C++中,经典的"(Shape)"造型并不履行RTTI.它只是简单地奉告编译器将对象当作新范例处理.而Java要履行范例查抄,这普通叫作“范例安全”的下溯造型.之所以叫“下溯造型”,是由于类分层构造的历史布列方法造成的.若将一个Circle(圆)造型到一个Shape(多少形状),就叫做上溯造型,因为圆只是多少形状的一个子集.反之,若将Shape造型至Circle,就叫做下溯造型.但是,固然我们明确知道Circle也是一个Shape,所以编译器可以自动上溯造型,但却不能保证一个Shape必定是一个Circle.因此,编译器不答应自动下溯造型,除非明确指定一次这样的造型.
RTTI在Java中存在三种情势.关键字instanceof奉告我们对象是不是一个特定范例的实例(Instance即“实例”).它会返回一个布尔值,以便以问题的情势利用,就象下面这样:
if(x instanceof Dog)
((Dog)x).bark();
将x造型至一个Dog前,上面的if语句会查抄对象x能否从属于Dog类.举行造型前,假如没有其他信息可以奉告自己对象的范例,那么instanceof的利用是非常重要的——不然会得到一个ClassCastException违例.
我们最普通的做法是查找一种范例(比方要变成紫色的三角形),但下面这个程序却演示了若何用instanceof标志出全部对象.
//: PetCount.java
// Using instanceof
package c11.petcount;
import java.util.*;

class Pet {}
class Dog extends Pet {}
class Pug extends Dog {}
class Cat extends Pet {}
class Rodent extends Pet {}
class Gerbil extends Rodent {}
class Hamster extends Rodent {}

class Counter { int i; }

public class PetCount {
  static String[] typenames = {
    "Pet", "Dog", "Pug", "Cat",
    "Rodent", "Gerbil", "Hamster",
  };
  public static void main(String[] args) {
    Vector pets = new Vector();
    try {
      Class[] petTypes = {
        Class.forName("c11.petcount.Dog"),
        Class.forName("c11.petcount.Pug"),
        Class.forName("c11.petcount.Cat"),
        Class.forName("c11.petcount.Rodent"),
        Class.forName("c11.petcount.Gerbil"),
        Class.forName("c11.petcount.Hamster"),
      };
      for(int i = 0; i < 15; i++)
        pets.addElement(
          petTypes[
            (int)(Math.random()*petTypes.length)]
            .newInstance());
    } catch(InstantiationException e) {}
      catch(IllegalAccessException e) {}
      catch(ClassNotFoundException e) {}
    Hashtable h = new Hashtable();
    for(int i = 0; i < typenames.length; i++)
      h.put(typenames[i], new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.elementAt(i);
      if(o instanceof Pet)
        ((Counter)h.get("Pet")).i++;
      if(o instanceof Dog)
        ((Counter)h.get("Dog")).i++;
      if(o instanceof Pug)
        ((Counter)h.get("Pug")).i++;
      if(o instanceof Cat)
        ((Counter)h.get("Cat")).i++;
      if(o instanceof Rodent)
        ((Counter)h.get("Rodent")).i++;
      if(o instanceof Gerbil)
        ((Counter)h.get("Gerbil")).i++;
      if(o instanceof Hamster)
        ((Counter)h.get("Hamster")).i++;
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(
        pets.elementAt(i).getClass().toString());
    for(int i = 0; i < typenames.length; i++)
      System.out.println(
        typenames[i] + " quantity: " +
        ((Counter)h.get(typenames[i])).i);
  }
} ///:~
在Java 1.0中,对instanceof有一个对比小的限制:只可将其与一个已命名的范例对比,不能同Class对象作比较.在上述例子中,大家大概认为将全部那些instanceof表达式写出来是件很麻烦的事情.实际情形恰是这样.但在Java 1.0中,没有办法让这一工作自动举行——不能成立Class的一个Vector,再将其与之对比.大家终究会意识到,如编写了数目众多的instanceof表达式,整个计划都大概呈现问题.
当然,这个例子只是一个假想——最好在每个范例里增添一个static数据成员,然后在构建器中令其增值,以便跟踪计数.编写程序时,大家大概想象自己拥有类的源码掌握权,可以安闲窜改它.但由于实际情形并非老是这样,所以RTTI显得分外便利.

1. 利用类标志
PetCount.java示例可用Java 1.1的类标志重写一遍.得到的后果显得越发明确易懂:
//: PetCount2.java
// Using Java 1.1 class literals
package c11.petcount2;
import java.util.*;

class Pet {}
class Dog extends Pet {}
class Pug extends Dog {}
class Cat extends Pet {}
class Rodent extends Pet {}
class Gerbil extends Rodent {}
class Hamster extends Rodent {}

class Counter { int i; }

public class PetCount2 {
  public static void main(String[] args) {
    Vector pets = new Vector();
    Class[] petTypes = {
      // Class literals work in Java 1.1+ only:
      Pet.class,
      Dog.class,
      Pug.class,
      Cat.class,
      Rodent.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // Offset by one to eliminate Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.addElement(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {}
      catch(IllegalAccessException e) {}
    Hashtable h = new Hashtable();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.elementAt(i);
      if(o instanceof Pet)
        ((Counter)h.get(
          "class c11.petcount2.Pet")).i++;
      if(o instanceof Dog)
        ((Counter)h.get(
          "class c11.petcount2.Dog")).i++;
      if(o instanceof Pug)
        ((Counter)h.get(
          "class c11.petcount2.Pug")).i++;
      if(o instanceof Cat)
        ((Counter)h.get(
          "class c11.petcount2.Cat")).i++;
      if(o instanceof Rodent)
        ((Counter)h.get(
          "class c11.petcount2.Rodent")).i++;
      if(o instanceof Gerbil)
        ((Counter)h.get(
          "class c11.petcount2.Gerbil")).i++;
      if(o instanceof Hamster)
        ((Counter)h.get(
          "class c11.petcount2.Hamster")).i++;
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(
        pets.elementAt(i).getClass().toString());
    Enumeration keys = h.keys();
    while(keys.hasMoreElements()) {
      String nm = (String)keys.nextElement();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) + 
        " quantity: " + cnt.i);
    }
  }
} ///:~
在这里,typenames(范例名)数组已被删除,改成从Class对象里获得范例名称.注意为此而额外做的工作:比方,类名不是Getbil,而是c11.petcount2.Getbil,此中已包含了包的名字.也要注意系统是可以辨别类和接口的.
也可以看到,petTypes的成立模块不需求用一个try块包抄起来,因为它会在编译期得到查抄,不会象Class.forName()那样“掷”出任何违例.
Pet动态成立好今后,可以看到随机数字已得到了限制,位于1和petTypes.length之间,并且不包含零.那是由于零代表的是Pet.class,并且一个普通的Pet对象大概不会有人感爱好.但是,由于Pet.class是petTypes的一部份,所以全部Pet(宠物)城市算入计数中.

2. 动态的instanceof
Java 1.1为Class类增添了isInstance办法.操纵它可以动态调用instanceof运算符.而在Java 1.0中,只能静态地调用它(就象前面指出的那样).因此,全部那些烦人的instanceof语句都可以从PetCount例子中删去了.以下所示:
//: PetCount3.java
// Using Java 1.1 isInstance()
package c11.petcount3;
import java.util.*;

class Pet {}
class Dog extends Pet {}
class Pug extends Dog {}
class Cat extends Pet {}
class Rodent extends Pet {}
class Gerbil extends Rodent {}
class Hamster extends Rodent {}

class Counter { int i; }

public class PetCount3 {
  public static void main(String[] args) {
    Vector pets = new Vector();
    Class[] petTypes = {
      Pet.class,
      Dog.class,
      Pug.class,
      Cat.class,
      Rodent.class,
      Gerbil.class,
      Hamster.class,
    };
    try {
      for(int i = 0; i < 15; i++) {
        // Offset by one to eliminate Pet.class:
        int rnd = 1 + (int)(
          Math.random() * (petTypes.length - 1));
        pets.addElement(
          petTypes[rnd].newInstance());
      }
    } catch(InstantiationException e) {}
      catch(IllegalAccessException e) {}
    Hashtable h = new Hashtable();
    for(int i = 0; i < petTypes.length; i++)
      h.put(petTypes[i].toString(),
        new Counter());
    for(int i = 0; i < pets.size(); i++) {
      Object o = pets.elementAt(i);
      // Using isInstance to eliminate individual
      // instanceof expressions:
      for (int j = 0; j < petTypes.length; ++j)
        if (petTypes[j].isInstance(o)) {
          String key = petTypes[j].toString();
          ((Counter)h.get(key)).i++;
        }
    }
    for(int i = 0; i < pets.size(); i++)
      System.out.println(
        pets.elementAt(i).getClass().toString());
    Enumeration keys = h.keys();
    while(keys.hasMoreElements()) {
      String nm = (String)keys.nextElement();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) + 
        " quantity: " + cnt.i);
    }
  }
} ///:~
可以看到,Java 1.1的isInstance()办法已撤消了对instanceof表达式的需求.此外,这也意味着一旦要求增添新范例宠物,只需简单地改变petTypes数组便可;毋需窜改程序剩余的部份(但在利用instanceof时倒是必须的).
  以上是“rtti在java造型前的查抄[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • java对RTTI的需求
  • java的rtti中class对象
  • rtti在java造型前的查抄
  • java的rtti机制语法
  • <b>java rtti学习总结</b>
  • <b>RTTI有害吗</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .