我是通配符的新手,对Java的泛型相对缺乏经验,并且在分配它们时遇到了问题。
我有一个自定义的通用类UserVariable<T>
。每个UserVariable都了解自己的两件事:其类型和其值,这在构造它的时候都是预期的。准系统定义如下所示:
class UserVariable<T extends Comparable<T>> implements Comparable<UserVariable<T>>
{
private T value;
private final transient Class<T> type;
public UserVariable(T value, Class<T> type)
{
this.value = value;
this.type = type;
}
public T getValue()
{
return value;
}
public Class<T> getType()
{
return type;
}
}
我在地图中存储了这些UserVariable的集合。我在定义Map时使用了通配符,以便可以将所有类型的UserVariable都存储在一个Map中。这里的想法是我的软件的用户正在创建变量并给它们命名,并且该软件可以使用变量名作为键在Map中存储/查找变量:
class VarsMap {
private ObservableMap<String, UserVariable<?>> userVars = FXCollections.observableHashMap();
public void setVariable(String name, UserVariable<?> variable)
{
userVars.put(name, variable);
}
public UserVariable<?> getVariable(String name)
{
return userVars.get(name);
}
}
稍后,我有一个类尝试检索此变量之一并存储其类型。我在最后一次作业时遇到了麻烦...
class SimpleComparison<T extends Comparable<T>> {
private StringProperty variableName = new SimpleStringProperty("");
private T comparisonValue;
private transient Class<T> myVarType;
public SimpleComparison(String variableName, T value, VarsMap theVars)
{
this.myVarType = theVars.getVariable(variableName).getType(); //error here
}
}
this.myVarType
定义为Class<T>
,并且UserVariable<T>
的getType()
方法应返回Class<T>
。同样,在构造每个type
时存储每个UserVariable
的UserVariable
。但是,最后一次赋值给出以下错误:类型不匹配:无法从
Class<capture#1-of ?>
转换为Class<T>
也许是因为Map是
UserVariable<?>
的地图?有人知道我在做什么错吗?谢谢你的帮助!编辑:最终我想做的是在
SimpleComparison
中有一个称为evaluate
的方法来执行此操作:public int evaluate(VarsMap theVars)
{
UserVariable<T> lhs = theVars.getVariable(variableName);
UserVariable<T> rhs = new UserVariable<T>(comparisonValue, myVarType);
return lhs.compareTo(rhs);
}
也就是说,我使用变量名和要比较的值构造了
SimpleComparison
对象。稍后,我在该对象上调用evaluate
,传入当前变量值的Map,它将当前变量值(从Map中获取)与构造时传入的比较值进行比较,并返回结果。但是,我不确定对
compareTo
的调用是否会起作用,因为lhs
希望为Class<?>
类型,而rhs
希望为Class<T>
类型。有没有办法按照我的意图去做?还是当我将其放入通配符对象的容器(在这种情况下为Map)时,对象的类型是否总是丢失? 最佳答案
泛型由编译器严格检查。因此,只要您维护与同一类型的其他实例相关的每个与onyl相关的泛型实例化,一切都很好:
MyGeneric<String> s1=...
MyOtherGeneric<String> o1=...
s1.doSomething(o1);
当您尝试混合类型时,问题就来了:
MyGeneric<String> s1=...
MyOtherGeneric<Double> o1=...
s1.doSomething(o1); // Error
好的,这很明显。在您的情况下,问题是相似的:您尝试将几种类型的常规实例(没有类型)收集到非常规抽象
VarsMap
中。因此,当您尝试将非通用
VarsMap
中包含的对象与通用对象Class<T>
混合在一起时,编译器如何确定它们的类型是否匹配?然后出现编译器错误。我看到的最简单的解决方案:由于您已经按名称匹配了
UserVariable
对象,并且我想每个变量始终具有相同的类型,因此您可以依靠此程序检查并假设它们的类型将匹配:只需添加一个方法范围的参数传递给getVariable
方法并进行简单的转换:public <T extends Comparable<T>> UserVariable<T> getVariable(String name)
{
return (UserVariable<T>)this.userVars.get(name);
}
...,并在调用它的地方添加适当的类型参数替换:
this.myVarType=theVars.<T> getVariable(variableName).getType();