我有以下代码as seen in ideone.com:
import java.util.*;
class Test{
interface Visitor{
public <T> void visit(T Value);
}
class MyVisitor<T> implements Visitor{
List<T> list = new ArrayList<T>();
public <T> void visit(T value){
list.add(value);
}
}
}
编译时,此代码将产生以下+错误:
Main.java:12: error: no suitable method found for add(T#1) list.add(value); ^ method List.add(int,T#2) is not applicable (actual and formal argument lists differ in length) method List.add(T#2) is not applicable (actual argument T#1 cannot be converted to T#2 by method invocation conversion) where T#1,T#2 are type-variables: T#1 extends Object declared in method visit(T#1) T#2 extends Object declared in class Test.MyVisitor 1 error
问题是访问中的类型T 与列表中的 T 不一样。我该如何解决这个编译问题?
答案 0 :(得分:8)
class MyVisitor<T> implements Visitor{
List<T> list = new ArrayList<T>();
public <T> void visit(T value){
list.add(value);
}
}
相当于
class MyVisitor<T> implements Visitor{
List<T> list = new ArrayList<T>();
public <V> void visit(V value){
list.add(value);
}
}
即。类的T
参数和T
方法的visit
参数不相关,也不一定要分配给另一个。如果Visitor
本身就是参数化界面
interface Visitor<V>{
public void visit(V Value);
}
那么你可以拥有MyVisitor<T> implements Visitor<T>
而T的 就可以了。
请记住,泛型方法的要点是链接两个或多个参数的类型,或者将参数的类型链接到方法的返回类型(例如,获取某种类型的参数并返回参数的方法) 相同类型的列表)。当泛型方法只使用它的参数一旦它没有真正从通用获得任何东西,即你将获得同样多的类型安全
interface Visitor{
public void visit(Object Value);
}
就像你原来的Visitor
界面一样。
答案 1 :(得分:1)
界面必须是Visitor<T>
编辑:界面必须如下所示
interface Visitor<T> {
void visit(T Value);
}
答案 2 :(得分:1)
您要声明通用类型<T>
两次:
visit
方法MyVisitor
班级编译器阻止添加到列表:list.add(value);
,因为这两种类型可能不同。
解决问题的一种方法是在Visitor
中使<T>
接口通用,并删除访问方法中的<T>
:
interface Visitor<T> {
public void visit(T Value);
}
class MyVisitor<T> implements Visitor<T>{
List<T> list = new ArrayList<T>();
public void visit(T value){
list.add(value);
}
}
答案 3 :(得分:0)
正确的解决方案是:
class Test {
interface Visitor<T> {
public void visit(T Value);
}
class MyVisitor<T> implements Visitor<T> {
List<T> list = new ArrayList<T>();
@Override
public void visit(T value) {
list.add(value);
}
}
}
答案 4 :(得分:0)
您将方法签名中的类型参数T
(以及MyVisitor<T>
中的项目类型)与方法签名中的类型参数list
相混淆,这可能是不同的完全打字。 (传递给visit()
的任何类型都可以是任何类型,也可以是Object
。)您应该重命名其中一个。
事实上,就Java泛型而言,访问者中的方法签名是无效的。只需将其设为void visit(Object o)
,它就完全相同而且不那么令人困惑。这样做也会使问题更加清晰,您尝试将Object
添加到List<T>
。如果您需要Visitor
中的方法签名,那么您必须进行投射。 (这需要Class.cast()
,因此Class<T>
中某处需要MyVisitor