![](/img/trans.png)
[英]Java generics - getting a method to return the same type as the first parameter
[英]Java Generics: getting return type from parameter
这是一个奇怪的问题。 我不认为有解决方案,但我想我还是会问。
假设我有一个枚举:
public enum Key {
RED(String.class),
GREEN(Integer.class),
BLUE(Short.class);
private Class<?> expectedType;
Key(Class<?> expectedType) { this.expectedType = expectedType; }
public Class<?> getExpectedType() { return expectedType; }
}
我想使用Key
枚举中的“ expectedType
”字段作为方法的返回类型。 看:
public class Cache {
private static Map<Key, Object> cache = new HashMap<>();
public void put(Key key, Object value) {
// Easy to validate that 'value' is of type key.getExpectedType()...
}
public <T> T get(Key key) {
Object value = cache.get(key);
// TODO need to define <T> as key.getExpectedType(). How?
}
}
看到那个 TODO 了吗? 我想让get()
定义由key
参数定义的“expectedType”的返回类型。 例如,如果key
参数是RED
, get()
方法将返回一个 String 并且您可以编写:
String s = cache.get(Key.RED);
有没有办法做到这一点? 我认为没有,但我很想听听一个聪明的解决方案。
枚举不支持 generics,但您可以使用常规 class 作为通用伪枚举:
public class Key<T> {
public static final Key<String> RED = new Key<>(String.class);
public static final Key<Integer> GREEN = new Key<>(Integer.class);
public static final Key<Short> BLUE = new Key<>(Short.class);
private final Class<T> expectedType;
private Key(Class<T> expectedType) { this.expectedType = expectedType; }
public Class<T> getExpectedType() { return expectedType; }
}
public class Cache {
private Map<Key<?>, Object> cache = new HashMap<>();
public <T> void put(Key<T> key, T value) {
cache.put(key, key.getExpectedType().cast(value));
}
public <T> T get(Key<T> key) {
return key.getExpectedType().cast(cache.get(key));
}
}
shmosel 的答案几乎可以肯定足以满足您的需求; 但是,它有一点限制,即您无法存储/检索泛型类型,因为您无法获得泛型类型的 class 文字。
相反,您可以使用Guava 的TypeCapture
之类的东西:
abstract class GenericKey<T> {
Type getExpectedType() {
return ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
}
这有点反光,你不应该花太多时间去看。
请注意,它是抽象的,因此您必须像这样实例化:
new GenericKey<Integer>() {}
这是创建一个GenericKey
的匿名子类,这是使其与泛型类型一起工作的魔力的一部分。
然后,它基本上是一样的:
public class Cache {
private Map<GenericKey<?>, Object> cache = new HashMap<>();
public <T> void put(GenericKey<T> key, T value) {
cache.put(key.getExpectedType(), value);
}
public <T> T get(GenericKey<T> key) {
return (T) cache.get(key.getExpectedType());
}
}
现在,如果您愿意,可以使用new new GenericKey<List<Integer>() {}
拥有一个GenericKey<List<Integer>>
。
这种方法的缺点是您无法在进出缓存的过程中检查值,因此如果您对原始类型粗心,您可能会受到堆污染。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.