假设我有一个由各种类实现的通用接口。
public interface MyInterface<K, V> {
// Some method declarations
// ...
// But owing to Java type erasure, we also have...
Class<K> getKClass();
Class<V> getVClass();
}
现在,我正在使用对象存储来获取实现MyInterface
的类的具体实例。而且在编写代码时,我还不知道参数K
和V
的类型。但是,可以访问预先存储的相应Class
对象。现在,我可以在请求工厂时使用它们。
public MyInterface getObjectFromStore(String uniqueKey,
Class kClazz, Class vClazz) {
MyInterface concreteInstance = MyClassWarehouse.retrieveObject(uniqueKey);
// Perform type checks.
boolean kMismatch = !kClazz.isAssignableFrom(concreteInstance.getKClass());
boolean vMismatch = ...;
// Mismatch handling...
...
// Everything's okay
return concreteInstance;
}
在我看来,如果我可以将方法编写为:
public <K, V> MyInterface<K, V> getObjectFromStore(String uniqueKey) {
try {
MyInterface<K, V> concreteInstance = MyClassWarehouse.retrieveObject(uniqueKey);
return concreteInstance;
} catch (ClassCastException cce) {
// Better way to handle type mismatch
...
}
}
但这要求我在编写代码时了解这些类。
MyInterface<String, Double> retrievedObject = getObjectFromStore("key123");
由于我只有类对象,因此必须使用第一种“分类器”方法。特别是:
// Must use this...
MyInterface retrievedObject = getObjectFromStore("key123", kClazz, vClazz);
// ... because this (or anything equivalent) is not possible.
MyInterface<kClazz, vClazz> retrievedObject = getObjectFromStore("key123");
在我看来,由于类型不是Java中的善意对象,因此无法从类对象K
和V
中获取类型标记kClazz
和vClazz
一种可以实现第二种方法的方式。但是,语法糖会很好。
还有其他原因无法启用此功能吗?
答案 0 :(得分:0)
如果您放弃编译时检查而转而使用运行时检查,则将需要来自两个源的运行时类型对象以进行任何比较。
因此,是的,最简单的方法是指定Class
对象的两端。在简单的情况下。
<T> void put(Class<T> t, T object);
<T> T get(Class<T> t);
添加特定的双重参数化类型(Java中没有更高类型的类型),这两个类型和一个键(对于严格的编程为boo)。
<K,V> void put(Class<K> k, Class<V> v, Key key, My<K,V> object);
<K,V> My<K,V> get(Class<K> k, Class<V> v, Key key);
有机会将三个关键对象组合为一个。
public final class MyKey<K,V> {
public static of(Class<K> k, Class<V> v, SimpleKey key) {
....
}
...
}
<K,V> void put(MyKey<K,V> key, My<K,V> object);
<K,V> My<K,V> get(MyKey<K,V> key);
或者,您可以寻找不同的类对象源。它们可以从方法签名中获得。
public interface MyReceiver<K,V> {
void accept(My<K,V> object);
}
/** @param receiver Runtime type should specialise type parameters. */
void get(MyReceiver<?,?> receiver);
({MyReciever<?,?>
可以是标准的Consumer<? extends MyReciever<?,?>>
。)
您可以将其他简单键添加为get
的参数(对lambda友好),MyReceiver
上的方法,accept
或MyReceiver
上的注释,或从MyReceiver
中删除该方法,并使用其运行时类型用作方法名称的任何名称(可能加上注释以查找所需的方法)。
实际上,这种在界面中指定所需类型的方法比旧式异构地图更现代。
(请注意,“存储库”是您仓库的标准术语。)