【问题标题】:Generic types : wildcards vs variables of raw types通用类型:通配符与原始类型的变量
【发布时间】:2013-03-20 07:24:34
【问题描述】:

考虑以下方法:

public static void listAll(LinkedList list) {

    for(Object obj : list)
        System.out.println(obj);

}

public static void listAll(LinkedList<?> list) {

    for(Object obj : list)
        System.out.println(obj);

}

这两种方法有什么区别?如果没有区别,为什么要使用第二个?

【问题讨论】:

  • 不同的是……等等,没有区别!
  • 不,我明白了。第二个使用通配符但没有出现。
  • 使用代码标签并编辑您的问题。
  • 第一个是非泛型的。列表中的所有内容都是您需要转换的 Object。第二个是通用的。类型将在编译时检查。
  • 感谢您的帮助,我不知道该怎么做。 :-)

标签: java oop generic-collections


【解决方案1】:

&lt;?&gt; 不允许您在列表中添加对象。请参阅下面的程序。它是我们传递给方法&lt;?&gt; 的特定类型的列表。
具体手段,列表以特定类型创建并传递给&lt;?&gt;方法listAll。不要与 word specific 混淆。
Specific 可以是任何普通对象,例如 Dog、Tiger、String、Object、HashMap、File、Integer、Long.... 并且列表无穷无尽。
JLS 强制 &lt;?&gt; 用于 不要在定义后在调用的&lt;?&gt;方法中执行添加任何irrelevant objects(在调用方法中定义不在called-listAll列表包含specific type 的对象。
就像&lt;?&gt;“别碰我”。

public static void listAll(LinkedList list) 
{
    list.add(new String());  //works fine
    for(Object obj : list)
            System.out.println(obj);

}
public static void listAll(LinkedList<?> list) 
{
     list.add(new String());  //compile time error. Only 'null' is allowed.
     for(Object obj : list)
          System.out.println(obj);
}

现在让我们看看不同的场景。当我们声明特定类型时会发生什么,例如 Dog、Tiger、Object、String ......任何东西。我们把方法改成specific type

public static void listAll(LinkedList<String> list)// It is now specific type, 'String'
{
    list.add(new String());//works fine. Compile time it knows that 'list' has 'String'
    for(Object obj : list)
         System.out.println(obj);
}

【讨论】:

  • > 不允许在列表中设置对象,但我们可以获取对象对吗?我们得到的对象类型是什么(在 getter() 方法中?是对象还是类型参数边界?
  • 总是对象类型。通用是为了方便。它照顾程序不误导编码。否则程序员会在运行时发现混乱。
  • @CenaPi 您应该查看 Joshua Bloch 在“Effective Java”中描述的“PECS”机制。 “生产者延伸,消费者超级”。通配符 > 与 extends Object>,所以“扩展”,因此是“生产者”。 “生产者”意味着您可以从列表中取出东西,但不能添加到列表中。
  • @SinaBarghidarian 在这种情况下,您可以添加任何Foo 对象。 ((List&lt;? super Foo&gt;) new LinkedList&lt;&gt;()).add(new Foo());
【解决方案2】:

List 是原始类型,List&lt;?&gt; 是带有通配符参数的泛型类型。

假设我们有以下变量:

List<?> a;
List<String> b;
List c;

赋值b=a 给出了编译时错误(List&lt;String&gt; 不能赋值给List&lt;?),但c=a 编译得很好(List&lt;String&gt; 可以赋值给原始类型List 以兼容不使用泛型的遗留代码)。

赋值b=c 给出编译时警告(List&lt;?&gt; 不可赋值给List&lt;String&gt;),但a=c 编译正常(List&lt;String&gt; 可赋值给List&lt;?&gt;

【讨论】:

  • 帮助!我需要更多解释
猜你喜欢
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
相关资源
最近更新 更多