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这里是类型参数,可用于确定列表的内容类型,但有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中的引用.