[英]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.