我目前正在与Generics合作,而我没有经验丰富。我遇到了这个问题:
我让这个课比较了实现Comparable
的2个值并做了其他一些事情,让我们说增加compareTo()
值:
public final class Type<T extends Comparable<T>> {
public int compare(T val1, T val2) {
int compTemp = val1.compareTo(val2);
compTemp++;
// do stuff
return compTemp;
}
}
现在我创建了Type
的一些实例:
Type<Integer> t1 = new Type<Integer>();
Type<String> t2 = new Type<String>();
现在我想将它们放入Map.
因为我无法预测Type
的泛型类型我使用了wilcard ?
:
Map<String, Type<?>> map = Maps.newHashMap();
map.put("t1", t1);
map.put("t2", t2);
如果我想调用Type.compare()
t1
,而不是map.get(t1)
:
t1.compare(1,1); // compiles fine
map.get("t1").compare(1, 1); // does not compile
后者抛出编译错误:
该类型的方法比较(捕获#3-of?,捕获#3-of?) Type不适用于参数(int,int)
我知道这是因为我的通配符参数,但我并不完全知道为什么以及如何解决这个问题。 唯一的#34;修复&#34;我看到是使用原始类型的Map,但是这会显示几个警告。 我想现在我对wilcard参数有很大的误解。
我感谢每一个答案!
答案 0 :(得分:2)
您在地图中使用wildcard <?>
表示您的地图不知道确切的类型。对于Map,它们都存储为Type<Object>
。
你可以做的一件事是某种类型的不安全的铸造
((Type<Integer>)map.get("t1")).compare(1, 1); // does compile but is type unsafe
另一种解决方案是在构造函数中创建Type
对象时存储泛型类。然后,您可以使用另一种方法泛型类型在compare
方法中进行某种类型的安全转换。请参阅此Type
类
public final class Type<T extends Comparable<T>> {
Class<T> type;
Type(Class<T> _type){
type = _type;
}
public <E extends Comparable<E>> int compare(E val1, E val2) {
T v1 = type.cast(val1);
T v2 = type.cast(val2);
int compTemp = v1.compareTo(v2);
compTemp++;
// do stuff
return compTemp;
}
}
现在你可以这样做:
Type<Integer> t1 = new Type<Integer>(Integer.class);
Type<String> t2 = new Type<String>(String.class);
Map<String, Type<?>> map = new HashMap<>();
map.put("t1", t1);
map.put("t2", t2);
map.get("t1").compare(1, 1); // compiles fine
map.get("t2").compare("one", "one"); // compiles fine
答案 1 :(得分:2)
我假设你想在运行时做这样的事情:
String key = getKeyFromParams(p1, p2);
map.get( key ).compare(p1, p2);
由于编译器不知道它为密钥返回的值的泛型类型,因此您不能以这种方式调用compare()。
但是,您可以稍微重构一下代码以使其正常工作(仍有警告并且需要注意不要破坏任何内容):
Comparable
参数示例:
public final class Type<T extends Comparable<T>> {
private final Class<T> typeClass;
public Type( Class<T> typeClass) {
this.typeClass = typeClass;
}
public int compare(Comparable val1, Comparable val2) {
if( !(typeClass.isInstance( val1 ) && typeClass.isInstance( val2 ) ) ) {
throw new IllegalArgumentException("message");
}
int compTemp = val1.compareTo(val2);
compTemp++;
// do stuff
return compTemp;
}
//getter for the typeClass
}
地图的包装:
class TypeComparator {
Map<Class<?>, Type<?>> map = new HashMap<Class<?>, Test.Type<?>>();
public void addType(Type<?> type) {
map.put( type.getTypeClass(), type );
}
public <T extends Comparable<T>> void compare(T p1, T p2) {
map.get( p1.getClass() ).compare( p1, p2 );
}
}
最后这样称呼它:
//add some types
TypeComparator comp = new TypeComparator();
comp.addType( new Type<Integer>( Integer.class ));
comp.addType( new Type<String>( String.class ));
//compare ints
comp.compare( 1, 1 );
//compare Strings
comp.compare( "1", "1" );
//won't compile
comp.compare( "1", 1 );
最后的一些想法:
Double
个参数)