在java泛型中使用通配符

时间:2013-08-09 01:53:07

标签: java

我试图理解java通用通配符。我遇到了一个基本程序。在我看来,唯一可以添加到列表中的是“null”。你无法添加 例如

s.add(new Integer (4)); 

OR

s.add(new Char(a));

在阅读大量材料并让我困惑之前,我试图了解Java设计人员在泛型中引入通配符的位置。从我的观点来看,我看不到任何有用的功能来自通用通配符。它是可能的因为我缺乏经验而且因为我是java的新手,所以看起来很好。如果人们可以分享他们对此事的看法,那就太好了。

import java.util.LinkedList;
import java.util.Iterator;

public class WildCardExampleOne {

    public static void main(String[] args)
    {
        LinkedList<?> s = new LinkedList<Integer>();
        s.add(null);

        Iterator<?> x = s.iterator();

        Object o = x.next();

        System.out.println(o);

        /* note that LinkedList<?> is NOT the same type as LinkedList<Object>
         * here are some statements that wouldn't compile:
         */
        // s.add(new Integer(3)); 
        // Iterator<Object> x = s.iterator();
    }
}

4 个答案:

答案 0 :(得分:6)

  

在我看来,唯一可以添加到列表中的是“null”。

是的,这是正确的。但是,您经常会收到一个您不需要(并且不应该)添加任何元素的列表。例如,考虑一个简单的方法,将列表的元素打印到标准输出,每行一个:

public static void printAll(final List<?> list) {
    for (final Object elem : list) {
        System.out.println(elem);
    }
}

此方法不需要知道列表的元素类型是什么;可以在List<String>ArrayList<Integer>LinkedList<Object>或任何其他List<?>上调用它。

答案 1 :(得分:2)

您不直接使用通配符实例化泛型类;您使用的是extendssuper

答案 2 :(得分:2)

@chylis是对的,只是为了补充他/她的评论,我会试着用简单的话来说:当然,通配符不允许你使用像setter这样的方法,但它们会让你做类似的事情这样:

public void doSomethingWithList(List<? extends Number> list) {

    for(Number number: list) {

        // do something with number

    }

}

你可以使用这个方法doSomethingWithList()使用List&lt; Integer&gt;,List&lt; Long&gt;,List&lt; Float&gt;等等,你肯定知道你正在处理{{1} (并使用像Number等方法),如果你只使用没有通配符的泛型,你必须使用相同的方法做这样的事情:

compareTo()

答案 3 :(得分:1)

查看适用于泛型的java文档:http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

我们的想法是你可以将它们用于方法类型:Collection<?>(发音为“unknown of unknown”)是方法的超类型。

它可以让你离开:

void printCollection(Collection<Object> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

对此:

void printCollection(Collection<?> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

Collection<?>允许您安全阅读元素,但不允许您安全地将元素存储到其中。

真正让你获益的地方就是:

public void drawAll(List<Shape> shapes) {
    for (Shape s: shapes) {
        s.draw(this);
    }
}

并将其重写为以下内容:

public void drawAll(List<? extends Shape> shapes) {
    ...
}

如果Cicle,则可以在课程class Circle extends Shape上使用。

希望这有助于您理解泛型。