我们正在尝试创建 Cache
的基本实现。在 java 。为此,我们创建了一个注释 @Cached
定义为:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cached {
<T> Class<T> keyClass();
<V> Class<V> valueClass();
String cacheId();
}
这会导致错误:
@interface members may not have type parameters
.然而,这是必需的,因为我们希望对返回方法的值进行类型转换并将它们存储在缓存中。我们正在使用 AspectJ
用于拦截需要缓存结果的方法调用。我们可以获得结果的另一种方式是什么?由于并非所有方法都具有相同的签名,因此我们必须依赖标记为
@Cached
的方法。对于我们的缓存实现。更新
这是在缓存中存储数据的类:
public class Cache<K extends Serializable, V> {
private Map<K, CacheEntry<V> cache;
// Some other fields and accessors
}
类(class)
CacheEntry
定义为:public class CacheEntry<V> {
private V value;
// Some other fields used for invalidating the cache entry and accessors
}
现在在访问缓存时,我想做这样的事情:
cache.getCache().values().stream()
.map(value -> cached.valueClass().cast(value))
.collect(Collectors.toList());
在上面的代码中,
cached
是@Cached
的引用方法上使用的注释为:@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
List<Person> findAll();
最佳答案
cached.valueClass().cast(value)
在这种情况下无法帮助您,主要是因为编译器无法强制执行 cached.valueClass()
兼容 Cached.valueClass()
.
通过类型转换帮助缓存客户端的最佳方法是让它们在读取时指定目标类型:
public <V> List<V> getAllCachedValues(Class<V> valueClass) {
return cache.getCache().values().stream()
.map(value -> valueClass.cast(value))
.collect(Collectors.toList());
}
或使用此未经检查的类型转换:
public <V> List<V> getAllCachedValues() {
return cache.getCache().values().stream()
.map(value -> (V) value)
.collect(Collectors.toList());
}
以下是一些用于说明尝试使用注释强制执行类型安全是多么不切实际的用法:
@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
List<Banana> findAll();
T
和 V
与实际缓存实例相关联(否则这将毫无意义,对吧?)。话虽如此,这是可能的:@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
//and then
Cache<Long, Banana> cacheInstance = cacheManager.getCache("personCache");
当然,您可以添加
Class
getCache
的参数:Cache<Long, Banana> cacheInstance = cacheManager.getCache("personCache",
Long.class, Banana.class);
并使用实际
Class
进行验证实例。但是,当您可以采用第一种方法(在检索时强制转换)时,这样做的意义何在……底线是调用者将最终确保类型兼容性,而注释元数据无济于事。 在我看来,
@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
如果您将缓存值序列化为 JSON 和 XML 等格式,并且需要原始类在缓存被命中时反序列化它们,则可能有助于输入(当然,希望客户端进行转换)。
关于java - 在 Java 中使用 Class<T> 作为注释的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58518232/