当前位置: 首页 > 面试题库 >

为什么Java类型参数没有下限?

东郭俊楠
2023-03-14
问题内容

我认为你不能将Java泛型类型参数绑定到下限(即使用super关键字)。我正在阅读Angelika Langer泛型常见问题解答对此主题的看法。他们说,这基本上可以归结为无用的下限(“没有任何意义”)。

我不相信。我可以想象它们的用途是帮助你更灵活地调用产生类型化结果的库方法的调用者。想象一下一个方法,该方法创建了用户指定大小的数组列表,并用空字符串填充了该列表。一个简单的声明是

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不允许使用的真正原因是什么?

P.S.

我知道更好的组织可能是这样的:

public static void populateListWithEmptyStrings(List<? super String> list, int size);

List<CharSequence> list = new ArrayList<CharSequence>();
populateListWithEmptyStrings(list, 5);

出于这个问题的目的,我们可以假装由于一项要求而需要在一个方法调用中同时执行这两种操作吗?

编辑
@Tom G(合理地)询问a相List<CharSequence>对于a有什么好处List<String>。首先,没有人说返回的列表是不可变的,所以这是一个优点:

List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
l2.add(new StringBuilder("foo").append("bar"));

问题答案:

基本上,它不够有用。

我认为你的示例指出了下限的唯一优势,即FAQ所称的功能Restricted Instantiation

最重要的是:“super” 绑定将为你提供的所有限制是,只能将Number的超类型用作类型实参。....

但是正如其他帖子所指出的那样,即使此功能的用处也可能受到限制。

由于多态性和专业化的性质,如FAQ(访问非静态成员和类型擦除)中所述,上限比下限有用得多。我怀疑下限引入的复杂性不值得其有限的价值。

OP:我想补充一点,我认为你确实表明它很有用,只是不够用。提出无可辩驳的杀手级用例,我将支持JSR。:-)



 类似资料:
  • 问题内容: 为什么大多数其他数据类型都没有Java的String基本类型? 问题答案: 字符串是一个对象,根本不是原始类型,只是一个字符数组。James Gosling的访谈 摘录摘述了Java中根本存在原始类型的原因,这很有趣。 Bill Venners: Java为什么会有原始类型?为什么不是所有事物都只是一个对象? James Gosling: 完全是效率问题。有各种各样的人已经建立了以in

  • 你好,我有两个类:Person类和Employee类,它们扩展了Person 我想写一个函数,将添加人到下界参数化列表 但是eclipse不允许它,错误消息是:“类型列表中的方法add(capture#1-of?super Employee)不适用于参数(Person)

  • 问题内容: Java枚举很棒。泛型也是如此。当然,由于类型擦除,我们都知道后者的局限性。但是有一件事我不理解,为什么我不能创建这样的枚举: 这样,该通用类型参数又可以在各个地方使用。想象一下方法的通用类型参数: 甚至在枚举类本身中: 更具体的例子#1 由于上面的示例对于某些人来说似乎太抽象了,因此下面是一个更现实的示例,说明了为什么要执行此操作。在这个例子中我想使用 枚举,因为这样我就可以枚举一组

  • 问题内容: 如果有Wrapper类使Java成为纯面向对象的语言,那么为什么会有可在Java中使用的Primitive数据类型呢? 问题答案: 为了效率。基本类型的变量直接包含值。非基本类型的变量是引用,引用存储在内存中其他位置的对象。 每次您需要使用包装器类型的值时,JVM都需要在内存中查找对象以获取该值。对于原始类型,这不是必需的,因为变量本身包含值,而不是对包含该值的对象的引用。 但是,这不

  • 问题内容: 众所周知,有多种原因(请参阅第一个答案)。为什么只有一个例外涵盖所有这些情况,而不是多个继承自的细粒度情况? 问题答案: 我期望如此,因为发生这种情况时,您实际上什么也做不了:为何耗尽资源几乎无关紧要,因为无论如何您都被搞砸了。也许附加信息会很好,但是… 我知道tomcat会尝试执行“内存不足降落伞”操作,在此过程中,它们会保留一块内存并尝试释放它,但是我不确定它的工作原理。

  • 我知道一个数据类型会自动提升到更高的数据类型byte-short-int