我试图了解如何在Java中使用通配符。
import java.util.List;
public class WildcardError{
void foo(List<?> i){
i.set(0, i.get(0));
}
}
public class WildcardFixed{
void foo(List<?> i){
fooHelper(i);
}
private <T> void fooHelper(List<T> l){
l.set(0, l.get(0));
}
}
void foo(Object i)
类似,或void foo(List<Object> i)
。答案 0 :(得分:2)
在第一个示例中,您可能已经传递了List<String>
,因此如果您使用Object(结果为l.get(0)
)设置元素,则实际上您无法安全地执行此类型操作。 一种近视观点。
在第二个示例中,l.get(0)
是T,完全适合l.set
,
答案 1 :(得分:2)
解释此https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
的好教程...
然而,向它添加任意对象是不安全的:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
由于我们不知道c的元素类型代表什么,我们无法向其添加对象。 add()方法接受类型为E的参数,即集合的元素类型。当实际类型参数为?时,它代表某种未知类型。我们传递给add的任何参数都必须是这种未知类型的子类型。由于我们不知道它是什么类型,我们无法传递任何内容。唯一的例外是null,它是每种类型的成员。
另一方面,给定List,我们可以调用get()并使用结果。结果类型是未知类型,但我们始终知道它是一个对象。因此,可以安全地将get()的结果赋给Object类型的变量,或者将其作为期望Object类型的参数传递。
答案 2 :(得分:1)
当我这样做时:
import java.util.ArrayList;
import java.util.List;
public class Wildcard {
public static void main(String[] args) {
WildcardFixed wf = new WildcardFixed();
List<Integer> li = new ArrayList<>();
li.add(0);
wf.foo(li);
System.out.println("Success");
}
}
class WildcardError{
void foo(List<?> i){
i.set(0, i.get(0));
}
}
class WildcardFixed{
void foo(List<?> i){
fooHelper(i);
}
private <T> void fooHelper(List<T> l){
l.set(0, l.get(0));
}
}
WildcardError
类无法使用消息
类型List中的方法set(int,capture#1-of?)不适用于参数(int,capture#2-of?)
在简洁的英语中,编译器说它不知道i
中包含什么类型的东西,即它不知道get()
返回的是什么类型的东西,它不知道set()
采用什么类型的参数,因此无法保证set()
操作会成功。
WildcardFixed
编译只是因为我们向编译器保证,无论l
中的任何类型如何,get
的结果都是同一类型,T
,作为set
的参数类型。编译器不需要太多工作,但它需要的不仅仅是?
。
但是,你可以变得更简单。如果您将类型参数T
放入原始foo()
方法中,则所有内容都会编译并完美运行。
import java.util.ArrayList;
import java.util.List;
public class Wildcard {
public static void main(String[] args) {
WildcardFixed wf = new WildcardFixed();
List<Integer> li = new ArrayList<>();
li.add(0);
wf.foo(li);
System.out.println("Success WildcardFixed");
WildcardWithT wt = new WildcardWithT();
wt.foo(li);
System.out.println("Success WildcardWithT");
}
}
class WildcardError{
void foo(List<?> i){
i.set(0, i.get(0));
}
}
class WildcardFixed{
void foo(List<?> i){
fooHelper(i);
}
private <T> void fooHelper(List<T> l){
l.set(0, l.get(0));
}
}
class WildcardWithT {
<T> void foo(List<T> i) {
i.set(0, i.get(0));
}
}