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

Java中未绑定通配符泛型的用途和要点是什么?

贺兴平
2023-03-14
问题内容

我不明白未绑定通配符泛型的用途。具有上限的绑定通配符泛型<? extends Animal>非常有意义,因为使用多态性,我可以使用该类型或集合。但是拥有可以是任何类型的泛型有什么意义呢?它是否违背了泛型的目的?编译器没有发现任何冲突,并且在类型擦除之后,就好像没有使用任何泛型一样。


问题答案:

当您的方法实际上并不关心实际类型时,未绑定类型可能很有用。

一个原始的例子是这样的:

public void printStuff(Iterable<?> stuff) {
  for (Object item : stuff) {
    System.out.println(item);
  }
}

由于PrintStream.println()可以处理所有引用类型(通过调用toString()),因此我们 不在乎
该引用的实际内容Iterable是什么。

来电者 可以在通过List<Number>Set<String>Collection<? extends MySpecificObject<SomeType>>

还要注意,根本不使用泛型(使用原始类型进行调用)会产生完全不同的效果:这会使编译器处理 整个对象 ,就好像泛型 根本不存在一样
。换句话说:不仅会忽略类的类型参数,还会忽略方法上的所有泛型类型参数。

另一个重要的区别是,您不能将任何(非null)值Collection<?>添加到,而可以将 所有 对象添加到原始类型Collection

这不会编译,因为的type参数c是未知类型(=通配符?),因此我们无法提供保证可分配给该值的值(null,可分配给所有引用类型的值除外)。

Collection<?> c = new ArrayList<String>();
c.add("foo");    // compilation error

如果不使用type参数(即使用原始类型),则可以向集合中添加 任何内容

Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());

请注意,编译器会 警告 您不要使用原始类型,尤其是出于这个原因:它会删除与泛型相关的所有类型检查。



 类似资料:
  • 问题内容: 与完全跳过它们相比,在类中使用通配符类型的泛型有什么优势吗? 问题答案: 有很多优点。 他们不会像使用原始类型那样产生编译器警告 它们提供了更多的类型安全性。例如,考虑是否是。如果您使用代替,则可以执行以下操作: 即使该列表仅 应 包含s。如果返回,则您将无法添加 任何 内容(除外),因为列表类型未知。 他们记录的东西与原始类型完全不同,即使用某种 未知但特定的类型进行输入 。

  • 这个问题的答案表明,当方法采用通配符泛型类型时,可以访问或修改集合,但不能同时访问或修改集合。(凯西和伯特) 据我所知,方法do1有,因此d2只能被访问,不能被修改。方法d2具有,因此可以访问和修改c2,并且没有编译错误。 通用指南

  • 问题内容: 我对Java中的通用通配符有两个疑问: 和之间有什么区别? 什么是有界通配符,什么是无界通配符? 问题答案: 在你的第一个问题中,并且是有界通配符的示例。无限制的通配符看起来像,基本上就是<? extends Object>。宽松地表示泛型可以是任何类型。有界通配符(或)通过说它必须扩展特定类型(称为上限)或必须是特定类型的祖先(称为下限)来对类型进行限制。

  • 所以我在阅读泛型以重新熟悉这些概念,尤其是在涉及通配符的地方,因为我很少使用或遇到通配符。从我的阅读中,我不明白他们为什么使用通配符。下面是我经常遇到的一个例子。 你为什么不这样写: oracle网站上的另一个示例: 为什么这不是写成 我错过什么了吗?

  • 问题内容: 以下这部分代码是什么意思?我什至不知道这个语法叫什么。 这是原始代码(可从此处找到:http : //developer.android.com/guide/components/processes-and- threads.html ): 问题答案: 告诉AsyncTask使用3种不同的类型进行描述,当您使用AsyncTask时,将String作为第一个参数,将Void作为第二个参数

  • 我试图理解为什么我们需要通配符——Java泛型中的问号,为什么我们不能使用普通的单字符t或E等作为类型?请看以下示例: 结果是一样的,尽管通配符版本更简洁。这是唯一的好处吗?