[英]How to safely fix this type mismatch on abstract method with generics and Supplier lambda
We have a cache framework which we use to wire application-specific cache types (such as this authentication cache shown below) to various implementations (eg ehcache, redis, memcached etc). 我们有一个缓存框架,可用于将特定于应用程序的缓存类型(例如下面显示的身份验证缓存)连接到各种实现(例如ehcache,redis,memcached等)。 The framework is just an abstraction layer to allow the application to define and manipulate its cache similar to a map of key-value pairs, while specifying its app-specific key class and value class.
该框架只是一个抽象层,允许应用程序在定义其特定于应用程序的键类和值类的同时,类似于键值对的映射来定义和操作其缓存。
So for example we have: 因此,例如,我们有:
public class AuthenticationCache extends BaseAuthenticationCacheImpl<AuthenticationCacheKey, AuthenticationCacheEntry> {...}
public class AuthenticationCacheKey implements IAuthenticationCacheKey {...}
public class AuthenticationCacheEntry implements IAuthenticationCacheEntry {...}
and elsewhere in the application, the app overrides an abstract method which provides a Supplier for its cache: 而在应用程序的其他位置,该应用程序会覆盖一个抽象方法,该方法为其缓存提供一个Supplier :
@Override
protected <K extends IAuthenticationCacheKey, E extends IAuthenticationCacheEntry> Supplier<BaseAuthenticationCacheImpl<K, E>> getAuthCacheSupplier() {
Supplier<BaseAuthenticationCacheImpl<K, E>> supplier = () -> {
return new AuthenticationCache();
};
}
But this creates a compiler error: 但这会导致编译器错误:
Type mismatch: cannot convert from AuthenticationCache to BaseAuthenticationCacheImpl
类型不匹配:无法从AuthenticationCache转换为BaseAuthenticationCacheImpl
Generics are kicking my backside these days. 这些天,仿制药正在踢我的后腿。 Am I doing this completely wrong?
我这样做是完全错误的吗? Can I safely cast the supplier to
(BaseAuthenticationCacheImpl<K,E>)
since I know after type erasure it'll be the same runtime and I know that the concrete key/value classes of AuthenticationCache
satisfy K,E (eg extends IAuthenticationCacheKey/IAuthenticationCacheEntry) ? 我可以安全地将供应商
(BaseAuthenticationCacheImpl<K,E>)
为(BaseAuthenticationCacheImpl<K,E>)
因为我知道类型擦除后,它将是相同的运行时,并且我知道AuthenticationCache
的具体键/值类满足K,E(例如,扩展了IAuthenticationCacheKey / IAuthenticationCacheEntry )?
You could cheat the compiler by using something like this: 您可以使用以下方法欺骗编译器:
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;
}
}
The cast is technically safe, as long as you can guarantee that K
and E
are always AuthenticationCacheKey
and AuthenticationCacheEntry
, but the compiler can't give you that guarantee. 只要您可以保证
K
和E
始终为AuthenticationCacheKey
和AuthenticationCacheEntry
,则转换在技术上是安全的,但是编译器无法提供此保证。
Assuming these classes: 假设这些类:
class BaseAuthenticationCacheImpl<K extends IAuthenticationCacheKey, E extends IAuthenticationCacheEntry> {}
interface IAuthenticationCacheKey {}
interface IAuthenticationCacheEntry {}
A safe solution is to change the return type to: 一个安全的解决方案是将返回类型更改为:
@Override
protected Supplier<BaseAuthenticationCacheImpl<?, ?>> getAuthCacheSupplier() {
return AuthenticationCache::new;
}
As long as the BaseAuthenticationCacheImpl
is just used to produce something that implements IAuthenticationCacheKey
and something that implements IAuthenticationCacheEntry
, but is not a consumer. 只要
BaseAuthenticationCacheImpl
仅仅是用于生产的东西,实现IAuthenticationCacheKey
和一些实现IAuthenticationCacheEntry
,而不是消费者。
Depending one how you actually use the type parameters of BaseAuthenticationCacheImpl
you might even be able to just drop them completely and exchange them for IAuthenticationCacheKey
and IAuthenticationCacheEntry
directly. 根据您实际使用
BaseAuthenticationCacheImpl
的类型参数的BaseAuthenticationCacheImpl
您甚至可以完全删除它们并将它们直接交换为IAuthenticationCacheKey
和IAuthenticationCacheEntry
。 (Sometimes the best solution to a generics problem is to not use generics) (有时,解决泛型问题的最佳方法是不使用泛型)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.