有人可以向我解释为什么以下代码不起作用吗?
public class Test {
interface Strategy<T> {
void execute(T t);
}
public static class DefaultStrategy<T> implements Strategy<T> {
@Override
public void execute(T t) {}
}
public static class Client {
private Strategy<?> a;
public void setStrategy(Strategy<?> a) {
this.a = a;
}
private void run() {
a.execute("hello world");
}
}
public static void main(String[] args) {
Client client = new Client();
client.setStrategy(new DefaultStrategy<String>());
client.run();
}
}
我收到以下错误:
The method execute(capture#3-of ?) in the type Test.Strategy<capture#3-of ?>
is not applicable for the arguments (String)
我通过改变代码来实现它,如下所示:
public class Test {
interface Strategy<T> {
void execute(T t);
}
public static class DefaultStrategy<T> implements Strategy<T> {
@Override
public void execute(T t) {}
}
public static class Client<T> {
private Strategy<T> a;
public void setStrategy(Strategy<T> a) {
this.a = a;
}
private void run(T t) {
a.execute(t);
}
}
public static void main(String[] args) {
Client<String> client = new Client<String>();
client.setStrategy(new DefaultStrategy<String>());
client.run("hello world");
}
}
但我想理解为什么原始方法不起作用。
答案 0 :(得分:11)
答案很简单:无法使用未绑定的通配符。它只是意味着“未知对象”。
它没有给编译器提供任何信息。 “?”无论什么类型的手段,所以实际上它太过于通用而不是任何意义。
看看这里:http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html
如上所述:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
由于我们不知道c的元素类型代表什么,我们无法向其添加对象。 add()方法接受类型为E的参数,即集合的元素类型。当实际类型参数为?时,它代表某种未知类型。我们传递给add的任何参数都必须是这种未知类型的子类型。由于我们不知道它是什么类型,因此我们无法传递任何内容。唯一的例外是null,它是每种类型的成员。
编辑:不用担心,当你开始使用它时,这是对java通配符的正常误解。这就是为什么存在有界通配符(例如。<? extends Something>
)的原因,否则通用通配符几乎是无用的,因为编译器不能对它做出任何假设。
答案 1 :(得分:0)
这不起作用,因为您的课程Client
是针对特定Strategy
(Strategy<?>
)编写的,但在run()
方法中,您传递了String
(这只适用于Strategy<String>
!)。这只有在您将a
的类型和setStrategy()
的参数更改为Strategy<String>
类型时才有效!
答案 2 :(得分:0)
这是因为这不是类型安全的操作。 “?”是一个通配符,这意味着我不知道类型。它并不意味着“任何类型”。读这个...... http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf