簡體   English   中英

如何使用泛型和Supplier Lambda在抽象方法上安全地解決此類型不匹配問題

[英]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;
    }

}

只要您可以保證KE始終為AuthenticationCacheKeyAuthenticationCacheEntry ,則轉換在技術上是安全的,但是編譯器無法提供此保證。

假設這些類:

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您甚至可以完全刪除它們並將它們直接交換為IAuthenticationCacheKeyIAuthenticationCacheEntry (有時,解決泛型問題的最佳方法是不使用泛型)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM