Java中的通配符捕获,无法调用方法

Java中的通配符捕获,无法调用方法,java,generics,design-patterns,wildcard,Java,Generics,Design Patterns,Wildcard,我目前有三个类,试图实现通用访问者模式,将其放入所有项目共享的库中: public interface Visitable<ReturnType> { public ReturnType accept(Visitor<?, ?> v); } public interface Visitor<SomeVisitable extends Visitable<?>, ReturnType> { public ReturnType

我目前有三个类,试图实现通用访问者模式,将其放入所有项目共享的库中:

public interface Visitable<ReturnType> {

    public ReturnType accept(Visitor<?, ?> v);

}

public interface Visitor<SomeVisitable extends Visitable<?>, ReturnType> {

    public ReturnType visit(SomeVisitable v);

}

public class BaseObject implements Visitable<Void>{
    public Void accept(Visitor<?, ?> v) {
        v.visit(this); //1
                       // The method visit(capture#1-of ?) in the type                                        
                       // Visitor<capture#1-of ?,capture#2-of ?> is not
                       // applicable for the arguments (BaseObject)
    }
}
公共界面可访问{
公共返回类型接受(访客v);
}
不支持公共接口访问者
//适用于参数(BaseObject)
}
}

为什么在
/1
处出现编译时错误?老实说,我真的不知道应该在代码中重新设计什么以使其编译。

您的问题显然是通配符的使用。
BaseObject
中的
accept
方法正在接受类型为
visitor
的访问者

仔细想想,现在编译器必须用以下通配符来填补
Visitor
接口中的空白:

interface Visitor<? extends Visitable<?>, ?> {
   ? visit(? v)
}
界面访问者,?>{
?访问(?v)
}
这些被填补的空白就是所谓的通配符捕获

现在,您尝试调用
visit(this)
。编译器究竟如何知道
this
的类型是否是由通配符
表示的实际类型?

正如@JBNizet所解释的,访问者背后的神奇之处在于,它在编译时知道所访问对象的所有可能替代方案。我真的怀疑在这里使用
访客
是个好主意


从代码示例中可以看出,问题的解决方案在于在访问者声明中使用实际的类型参数,而不是通配符。

这没有多大意义。为了有用,访问者接口应该为BaseObject的每个子类提供一个visit()方法。所以它不应该是泛型的。你试过
?扩展BaseObject
?@jbnize您的意思是访问者实现不应该是通用的吗?如果是这样的话,我不同意你的看法,因为如果我们把所有这些员工都放在一个库中,我们将编写更可读、更简单的代码,并避免创建那些样板类。这不是很好吗?你可以做一辆普通车,但如果它没有任何轮子或引擎,那就没用了。了解visitor模式是关于什么的,您将认识到使用该模式的意义。这是一个很好的例子,说明了设计模式是如何“半生不熟”的解决方案,需要付出努力才能应用。它们的好处是以代码复杂性为代价的。考虑这一点的另一种方式是谦虚:访客模式至少从1995年(也就是20多年)就有了记录。如果这样一个通用的解决方案是可能的,那么它不是已经在JavaAPI中了吗,比如说,像Observer?