泛型类型和通配符类型之间的区别

Fio*_*Fio 49 java generics wildcard

我是Generic的新手,我的问题是:两个函数之间有什么区别:

功能1:

public static <E> void funct1  (List<E> list1) {

}
Run Code Online (Sandbox Code Playgroud)

功能2:

public static void funct2(List<?> list) {

}
Run Code Online (Sandbox Code Playgroud)

谢谢.

Jen*_*der 34

第一个签名是:list1是Es的列表.

第二个签名说:list是某种类型的实例列表,但我们不知道类型.

当我们尝试更改方法时,差异变得明显,因此它需要第二个参数,该参数应该添加到方法内的列表中:

import java.util.List;

public class Experiment {
    public static <E> void funct1(final List<E> list1, final E something) {
        list1.add(something);
    }

    public static void funct2(final List<?> list, final Object something) {
        list.add(something); // does not compile
    }
}
Run Code Online (Sandbox Code Playgroud)

第一个很好用.并且您不能将第二个参数更改为实际编译的任何内容.

实际上我只是发现了一个更好的差异演示:

public class Experiment {
    public static <E> void funct1(final List<E> list) {
        list.add(list.get(0));
    }

    public static void funct2(final List<?> list) {
        list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
    }
}
Run Code Online (Sandbox Code Playgroud)

有人可能为什么我们需要<?>它只限制我们可以用它做什么(正如@Babu_Reddy_H在评论中所做的那样).我看到了通配符版本的以下好处:

  • 调用者必须更少了解他传入的对象.例如,如果我有一个列表映射:Map<String, List<?>>我可以将其值传递给您的函数,而无需指定列表元素的类型.所以

  • 如果我分发像这样参数化的对象,我会主动限制人们对这些对象的了解以及它们可以用它做什么(只要它们远离不安全的铸造).

当我将它们组合时,这两个是有意义的:List<? extends T>.例如,考虑一种方法List<T> merge(List<? extends T>, List<? extends T>),该方法将两个输入列表合并到新的结果列表中.当然你可以引入另外两个类型参数,但你为什么要这样做?它将过度指定事物.

  • 最后通配符可以有下限,所以使用列表可以使add方法工作,get而不会给你任何有用的东西.当然,这会触发下一个问题:为什么泛型没有下限?

有关更深入的答案请参阅:何时使用通用方法以及何时使用通配符?http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203

  • 值得注意的是,这不仅仅是看跌期权.使用`List <E>`,您可以编写`E obj = list.get(0)`,但是使用`List <?>`,您只能编写`Object obj = list.get(0)`. (5认同)

Kum*_*tra 7

泛型使集合更安全.

List<E>:E这里是类型参数,可用于确定列表的内容类型,但有No办法检查期间的内容是什么runtime.

Generics are checked only during compilation time.
Run Code Online (Sandbox Code Playgroud)

<? extends String>:这是专门构建到java中,用于处理Type Parameter的问题."? extends String"意味着这个名单可以有

objects which IS-A String.
Run Code Online (Sandbox Code Playgroud)

例如:

动物类狗类延伸动物虎类延伸动物

所以使用 "public void go(ArrayList<Animal> a)"NOT accept狗或虎作为其内容但动物.

"public void go(ArrayList<? extends Animal> a)" 是什么需要制作 ArrayList take in Dog and Tiger type.

检查Head First Java中的引用.