大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 没有泛型之前

考虑您要设计下面的两个类(两个很无聊的类,但足以说明需求):
  • BooleanFoo.java
public class BooleanFoo {
private Boolean foo;

public void setFoo(Boolean foo) {
this.foo = foo;
}

public Boolean getFoo() {
return foo;
}
}
  • IntegerFoo.java
public class IntegerFoo {
private Integer foo;

public void setFoo(Integer foo) {
this.foo = foo;
}

public Integer getFoo() {
return foo;
}
}

类定义时逻辑完全一样,只是当中声明的成员类型不同,有点小聪明的程序设计人员会将第一个类的内容复制至另一个文件中,然后用编辑器“取代”功能一次取 代所有的类型名称(即将Boolean取代为Integer)。

OK!是有些小聪明,但还是不太聪明,如果类中的逻辑要修改,您要修改两个文件,泛型(Generics)的需求就在此产生,当您定义类 别时,发现到好几个类的逻辑其实都相同,就只是当中所涉及的类型不一样时,使用复制、贴上、取代的功能来撰写程序只是让您增加不必要的文件管理困扰,有 没有办法只写一个文件就好,毕竟它们的逻辑是相同的。

别忘了,Java中所有的类都继承自Object,这样写会比较好:

  • ObjectFoo.java
public class ObjectFoo {
private Object foo;

public void setFoo(Object foo) {
this.foo = foo;
}

public Object getFoo() {
return foo;
}
}

由于Java中所有定义的类,都以Object为最上层的父类,所以用它来实现泛型(Generics)功能是一个不错的考量,大部份的人都这么作,您只要撰写这么一个类,然后可以如下的使用它:
ObjectFoo foo1 = new ObjectFoo();
ObjectFoo foo2 = new ObjectFoo();

foo1.setFoo(new Boolean(true));
// 记得转换接口
Boolean b = (Boolean) foo1.getFoo();

// 记得转换接口
foo2.setFoo(new Integer(10));
Integer i = (Integer) foo2.getFoo();

看来还不错,但是由于传回的是Object,您必须转换它的接口,问题出在这边,粗心的程序设计人员往往会忘了要作这个动作,或者是转换接口时用错了类型(像是该用Boolean却用了Integer),例如:
ObjectFoo foo1 = new ObjectFoo();
foo1.setFoo(new Boolean(true));
String s = (String) foo1.getFoo();
 

要命的是,语法上是可以的,所以编译器检查不出错误,真正的错误要在运行时才会发生,这时恼人的ClassCastException就会出来搞怪,在使用Object设计泛型程序时,程序人员要再细心一些、小心一些。