繁体   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