[英]How to safely fix this type mismatch on abstract method with generics and Supplier lambda
我们有一个缓存框架,可用于将特定于应用程序的缓存类型(例如下面显示的身份验证缓存)连接到各种实现(例如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>)
为(BaseAuthenticationCacheImpl<K,E>)
因为我知道类型擦除后,它将是相同的运行时,并且我知道AuthenticationCache
的具体键/值类满足K,E(例如,扩展了IAuthenticationCacheKey / IAuthenticationCacheEntry )?
您可以使用以下方法欺骗编译器:
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;
}
}
只要您可以保证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
的类型参数的BaseAuthenticationCacheImpl
您甚至可以完全删除它们并将它们直接交换为IAuthenticationCacheKey
和IAuthenticationCacheEntry
。 (有时,解决泛型问题的最佳方法是不使用泛型)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.