【问题标题】:Why we can instantiate Pair<T> but we can't with Pair<?>为什么我们可以实例化 Pair<T> 但我们不能用 Pair<?>
【发布时间】:2012-12-20 21:46:22
【问题描述】:

那么为什么我们可以实例化 Pair 但我们不能实例化 Pair

Pair<T> p=new Pair<T>();

VS

Pair<?> p=new Pair<?>();

我知道&lt;?&gt; 表示未知类型 --> &lt;? extends Object&gt;

&lt;T&gt; 不是同一个意思 ---> &lt;T extends Object&gt;

有人有想法吗?

【问题讨论】:

    标签: java generics wildcard type-parameter bounded-wildcard


    【解决方案1】:

    &lt;T&gt; 本身并不意味着什么。 T 类型必须在某个地方定义,无论是在您的类还是方法级别,例如:

    public class PairFactory<T> {
      public Pair<T> makePair() {
        return new Pair<T>();
      }
    }
    

    在这种情况下,您在实例化期间决定&lt;T&gt;

    new PairFactory<String>();
    

    这有点牵强:

    public <T> Pair<T> makePair() {
      return new Pair<T>();
    }
    

    编译器会尝试根据上下文来判断类型,例如:

    Pair<Date> p = makePair();
    

    【讨论】:

    • @skystar7:这就是我要解释的内容(如果不清楚,请原谅):new Pair&lt;T&gt; 有效,因为T 是在更早的地方定义的。 &lt;?&gt; 只是一个占位符,new Pair&lt;?&gt; 从未完全定义
    • 谢谢...我明白你的意思了
    • 如果编译器不知道它是什么类型的对象,它如何为它分配内存??
    • @jahroy:首先,它知道,T 在编译时是已知的。其次它不必知道,这些对象几乎没有references 来键入T。引用只是 32 位或 64 位指针。稍后由您来创建上述对象。
    • 我指的是何时使用&lt;?&gt; 而不是&lt;T&gt;(但我的评论可能还很遥远)...
    【解决方案2】:

    不,?和 T 不是一回事。 ?表示一个通配符泛型类型参数——它可以是运行时的任何东西。 T 表示一个泛型类型参数,在运行时将是特定类型——我们只是在编译时不知道它。

    也就是说,List&lt;?&gt; 可以包含字符串、整数、浮点数等。List&lt;T&gt; 只能包含 T 参数化为的任何内容。

    【讨论】:

      【解决方案3】:

      不允许使用通配符作为参数进行实例化,因为它通常是无用的。相反,您可以只使用类型参数范围内的 any 引用类型(在这种情况下,没有边界,因此只有任何引用类型):

      class SuperCrazyBogusType { }
      Pair<?> p = new Pair<SuperCrazyBogusType>();
      

      (或者您可以使用更普通的类型,例如Object)。

      你知道这有多奇怪吗?是的,您可以使用任何任意类型进行实例化,即使是与您的程序的其余部分或您正在做的事情无关的类型。是的,它是 100% 安全和正确的,因为您想要的只是 Pair&lt;?&gt;(一对未知类型)。

      这指出了为什么它是荒谬的,以及为什么这样做的语法是不必要的。得到的Pair&lt;?&gt; 几乎无能为力(例如,您不能将任何数据放入其中),因为您不知道类型参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-19
        • 2021-03-24
        • 2013-03-22
        • 2011-07-18
        • 1970-01-01
        • 2015-08-05
        • 1970-01-01
        相关资源
        最近更新 更多