泛型与继承
类型变量的限定
有时,类或方法需要对类型变量加以约束。下面是一个典型的例子,我们要计算数组中的最小元素:
class ArrayListUnit
{
public static <T> T t (T ...args)
{
T item = args[0];
for (int i=1; i < args.length; i++)
if (item.compareTo(args[i]) > 0)
item = args[i];
return item;
}
}
该代码会编译失败,这里有个问题,变量args类型为T,这意味着它可以是任何一个类的对象。如何知道T所属的类有一个compareTo方法呢?
解决这个问题的方法是限制T只能是实现了Comparator接口的类。可以通过对类型变量做一个限定:
public static <T extends Comparable<T> T t (T ...args)
注意,这里使用的是extends关键字,而不是implements。
表示T应该是限定类型(boundingType)的子类型(subtype)。T和限定类可以是类,也可以是接口。<T extends BoundingType>
一个类型变量或通配符可以有多个限定,例如:
T extends Comparable & Clonable
限定类型用&隔开,而逗号用来分割类型变量。
<T extends Object, U extends Comparable>
在java的继承中,可以根据需要拥有多个接口超类型,但最多有一个限定可以是类,如果有一个类作为限定,它必须是限定列表中的第一个。
最后,来改写上述方法
package com.studyjava.demo;
import java.util.*;
public class Demo19
{
public static void main (String[] args)
{
System.out.println(ArrayListUnit.min(3,23,12));
System.out.println(ArrayListUnit.min("php", "java", "c++", "golang", "c#"));
}
}
class ArrayListUnit
{
public static <T> ArrayList<T> arrayListAdd (T ...elements)
{
ArrayList<T> ts = new ArrayList<>();
for (T e : elements) {
ts.add(e);
}
return ts;
}
public static <T extends Comparable<T>> T min (T ...args)
{
T item = args[0];
for (int i=1; i < args.length; i++)
if (item.compareTo(args[i]) > 0)
item = args[i];
return item;
}
}
泛型在继承中的体现
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的 类或接口,G并不是G的子类型!
比如:String是Object的子类,但是List并不是List 的子类。
下面,我们用一段代码来验证上述结论:
class Util
{
public static void show (ArrayList<Object> list)
{
for (Object o : list) {
System.out.println(o);
}
}
}
ArrayList<Object> objects = new ArrayList<>();
objects.add(23);
objects.add("hello");
objects.add(23.1);
ArrayList<String> strings = new ArrayList<>();
strings.add("hello");
strings.add("java");
strings.add("&php");
Util.show(objects); // ok
Util.show(strings); // error
如果ArrayList