我们有一个缓存框架,用于将特定于应用程序的缓存类型(例如下面显示的此身份验证缓存)连接到各种实现(例如ehcache,redis,memcached等)。该框架只是一个抽象层,允许应用程序定义和操作其缓存,类似于键值对的映射,同时指定其特定于应用程序的键类和值类。
例如我们有:
public class AuthenticationCache extends BaseAuthenticationCacheImpl<AuthenticationCacheKey, AuthenticationCacheEntry> {...}
public class AuthenticationCacheKey implements IAuthenticationCacheKey {...}
public class AuthenticationCacheEntry implements IAuthenticationCacheEntry {...}
以及应用程序中的其他位置,应用程序会覆盖为其缓存提供 Supplier 的抽象方法:
@Override
protected <K extends IAuthenticationCacheKey, E extends IAuthenticationCacheEntry> Supplier<BaseAuthenticationCacheImpl<K, E>> getAuthCacheSupplier() {
Supplier<BaseAuthenticationCacheImpl<K, E>> supplier = () -> {
return new AuthenticationCache();
};
}
但这会产生编译错误:
类型不匹配:无法从AuthenticationCache转换为 BaseAuthenticationCacheImpl
仿制药现在正在踢我的背后。我这样做完全错了吗?我可以安全地将供应商转换为(BaseAuthenticationCacheImpl<K,E>)
,因为我知道在类型擦除之后它将是相同的运行时并且我知道AuthenticationCache
的具体键/值类满足K,E(例如, IAuthenticationCacheKey / IAuthenticationCacheEntry)?
答案 0 :(得分:0)
您可以通过使用以下内容来欺骗编译器:
protected <K extends IAuthenticationCacheKey, E extends IAuthenticationCacheEntry> Supplier<BaseAuthenticationCacheImpl<K, E>> getAuthCacheSupplier() {
return () -> new AuthenticationCache().toBaseAuthenticationCacheImpl();
}
class AuthenticationCache extends BaseAuthenticationCacheImpl<AuthenticationCacheKey, AuthenticationCacheEntry> {
public BaseAuthenticationCacheImpl toBaseAuthenticationCacheImpl(){
return this;
}
}
答案 1 :(得分:0)
演员在技术上是安全的,只要您可以保证K
和E
总是AuthenticationCacheKey
和AuthenticationCacheEntry
,但编译器无法提供你保证。
假设这些类:
class BaseAuthenticationCacheImpl<K extends IAuthenticationCacheKey, E extends IAuthenticationCacheEntry> {}
interface IAuthenticationCacheKey {}
interface IAuthenticationCacheEntry {}
安全的解决方案是将返回类型更改为:
@Override
protected Supplier<BaseAuthenticationCacheImpl<?, ?>> getAuthCacheSupplier() {
return AuthenticationCache::new;
}
只要BaseAuthenticationCacheImpl
仅用于生成实现IAuthenticationCacheKey
的内容以及实现IAuthenticationCacheEntry
但不是消费者的内容。
根据您实际使用BaseAuthenticationCacheImpl
类型参数的方式,您甚至可以完全删除它们并直接与IAuthenticationCacheKey
和IAuthenticationCacheEntry
进行交换。 (有时候泛型问题的最佳解决方案是不使用泛型)