我认为您不能将 Java 泛型类型参数绑定到下限(即使用super
关键字)。我正在阅读Angelika Langer Generics 常见问题解答关于该主题的内容。他们说这基本上归结为无用的下限(“没有任何意义”)。
我不相信。我可以想象使用它们来帮助您对产生类型化结果的库方法的调用者更加灵活。想象一个创建用户指定大小的数组列表并用空字符串填充它的方法。一个简单的声明是
public static ArrayList<String> createArrayListFullOfEmptyStrings(int i);
但这对您的客户来说是不必要的限制。为什么他们不能像这样调用你的方法:
//should compile
List<Object> l1 = createArrayListFullOfEmptyStrings(5);
List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
List<String> l3 = createArrayListFullOfEmptyStrings(5);
//shouldn't compile
List<Integer> l4 = createArrayListFullOfEmptyStrings(5);
在这一点上,我很想尝试以下定义:
public static <T super String> List<T> createArrayListFullOfEmptyStrings(int size) {
List<T> list = new ArrayList<T>(size);
for(int i = 0; i < size; i++) {
list.add("");
}
return list;
}
但它不会编译;在这种情况下,super
关键字是非法的。
我上面的例子是一个坏例子吗(忽略我下面所说的)?为什么下限在这里没有用?如果它有用,那么在 Java 中不允许它的真正原因是什么?
附言
我知道一个更好的组织可能是这样的:
public static void populateListWithEmptyStrings(List<? super String> list, int size);
List<CharSequence> list = new ArrayList<CharSequence>();
populateListWithEmptyStrings(list, 5);
出于这个问题的目的,我们可以假设由于需求,我们需要在一个方法调用中执行这两项操作吗?
编辑
@Tom G(有理由)询问拥有 aList<CharSequence>
对 a 有什么好处List<String>
。一方面,没有人说返回的列表是不可变的,所以这里有一个优点:
List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
l2.add(new StringBuilder("foo").append("bar"));