我正在设计一个容器类,用于保存
的一对实现public interface MetaData<ValueType>{
public String getName();
}
和ValueType
Type参数的对应值。所以我写了这个(强制执行一些不变的):
public final class ParametersImpl implements Parameters{
private final Map<MetaData<?>, Object> parameters;
{
parameters = new HashMap<>();
}
@Override
public Object getValue(MetaData<?> pmd) {
return parameters.get(pmd);
}
@Override
public <M> void put(MetaData<M> p, M value) {
parameters.put(p, value);
}
}
其中
public interface Parameters {
public Object getValue(MetaData<?> pmd);
public <M> void put(MetaData<M> p, M value);
}
当客户端调用方法Object getValue(MetaData<?> pmd)
时,他们必须进行显式转换:
MetaData<List<Integer>> metaData;
Paramters params;
List<Integer> list= new ArrayList<>();
//intialization
params.put(metaData, list);
//do some other
List<Integer> lst = (List<Integer>) params.getValue(metaData);
虽然演员表是完全安全的,但我想避免它并提供某种通用方法。但是当我尝试这个宣言时:
public <M> M getValue(MetaData<M> pmd);
我在实现中遇到了编译错误:
public <M> M getValue(MetaData<M> pmd) {
return parameters.get(pmd); //cannot convert capture-of-#1 to M
}
问题: 有没有办法以任何方式生成方法public Object getValue(MetaData<?> pmd);
?
答案 0 :(得分:2)
您只需要转换从地图中检索到的值:
public <M> M getValue(MetaData<M> pmd) {
return (M) parameters.get(pmd);
}
但是此时编译器抱怨它无法检查强制转换。这是什么意思?好吧,Java源代码中的普通强制转换用(SomeType) val
表示 - 编译器检查操作是否完全非法(例如,您不能转换String
引用到Integer
)并发出一个在运行时执行的字节码,它可能会抛出ClassCastException
。
当您使用类型变量强制转换引用时,编译器无法发出这样的字节码,因为类型变量在运行时不存在 - 因此会发出编译警告。你应该:
@SuppressWarnings("unchecked")