Java 泛型编程详解(3)

五、泛型方法与泛参界限的综合
    如果说泛型方法是一个有用的工具,那泛参的界限就应该这个工具的灵魂,为这个工具添加了一些“行为准则”。如下:设计一个方法,统计在一个数组里比指定元素大的个数,
public static <T> int countGreater(T[] array,T elem) {
  int count = 0;
  for (T t : array) {
   if (t > elem) {//编译错误
    ++count;
   }
  }
  return  count;
 }
    发现上面这个方法无法通过编译,为什么呢??因为操作符“>”只可以用在基本数据类型(byte,char,short,int,float,long,double,boolean),却不可以用来比较类对象之间的大小(除非实现了Comparable接口)。想要解决这个矛盾,就需要为<T>添加一个界限Comparable<T>:
public interface Comparable<T> {
    public int compareTo(T o);
}
    更改后的代码如下:
public static <T extends Comparable<T>> int countGreater(T[] array,T elem) {
  int count = 0;
  for (T t : array) {
   if (t.compareTo(elem) > 0) {//无编译错误
    ++count;
   }
  }
  return  count;
 }
    除了上述方式,也可以选择添加界限Comparator<T,T>,只不过此界限需要两个参数而已,Comparator的定义与使用以前已经谈过,这里不再累述,详情可以点击 这里。
六、泛型、继承与子类型
    如果两个类之间相互兼容(继承与被继承),那么便可以将一个类对象赋值给另一个类对象,比如:你可以将一个String对象赋值给Object,String是Object的子类,
String someString = new String();
Object someObject = new Object();
someObject = someString;
    如果你熟悉面向对象技术,会知道这是一种“is-a”关系。String是Object的一种对象,所以上面的赋值是可以的。同理,Integer、Double是Number的一类对象,下面的赋值也可以:
public void someMethod(Number n) { /* ... */ }

someMethod(new Integer(10));  // OK
someMethod(new Double(10.1);  // OK
    这种“is-a”关系,同样也是用泛型。如果你将泛参设置Number,那么在随后的调用里,只需要传入一个数据对象就行了,如下:
Box<Number> box = new Box<>();
box.add(new Integer(1)); 
box.add(new Double(1.0));
    现在,考虑一下下面这种方法:
public void someMethod(Box<Number> n) { /*.....*/}
    这个方法可以接受什么类型的参数呢??显然,这个方法接受Box<Number>类型的参数??那又是否可以接受Box<Integer>或者Box<Double>类型的参数的??答案是否定的,因为Box<Integer>与Box<Double>都不是Box<Number>的子类。在泛型编程里,这是一个容易混淆的概念,但又必须要懂的原理。如下图:

Java 泛型编程详解

从图可以看到,即使Integer是Number的子类,但Box<Integer>并不是Box<Number>的子类。Box<Integer>与Box<Number>的共同父类是Object。换言之,无论类A与类B是否存在关联,MyClass<A>与MyClass<B>都没有任何关联,其共同的父类的是Object。那是否说,泛型就不存在子类呢??这个留待解决,看完本文便可以知晓。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/9307b3733a59ee9ea5993502cfb73bf1.html