我有以下界面:
CacheKey界面:
public interface CacheKey<K extends Serializable> extends Serializable {
K get();
}
CacheValue接口:
public interface CacheValue<V extends Serializable> extends Serializable {
V get();
}
缓存接口:
public interface Cache<CacheKey<K extends Serializable>, CacheValue<V extends Serializable>> {
}
缓存接口无法编译。我得到的错误是: [13,35]>预期
即在CacheKey编译器不喜欢另一个开口尖括号之后:
public interface Cache<CacheKey<
^
这在Java中是不可能的吗?
答案 0 :(得分:0)
在未编译的代码段中,CacheKey
实际上是一个类型参数(不引用上面创建的接口),这就是为什么在该位置不允许再有尖括号。
如果您想限制Cache
接口的通用类型,则可以使用以下内容:
public interface Cache<K extends CacheKey<?>, V extends CacheValue<?>> {
void cache(K key, V value);
default Serializable dummyMethod(K key, V value) {
return key.get();
}
}
我们可以在此处使用通配符(?
,因为CacheKey
和CacheValue
的通用类型已经绑定到Serializable
。
答案 1 :(得分:0)
您在这里错过了关键步骤:实施。
通常要在实现中定义? extends Serializable
的类型。您无需在Cache
界面中实现此功能。
接口仅需要知道其泛型类型是什么,而不是其子级的泛型:这是用于实现的。
请看下面的示例,以了解我的确切意思。
添加:定义Cache<CacheKey, CacheValue>
之类的内容时,您不是在引用类,而是在创建通用别名。 CacheKey
可以很容易地被Blabla
取代,并继续具有相同的行为。解决方案是使用extends
以确保我们在谈论类型。
这也是Cache<CacheKey<...>>
未编译的原因,因为CacheKey
并未引用该类,但被用作别名
public interface CacheKey<K extends Serializable> extends Serializable {
K get();
}
public interface CacheValue<V extends Serializable> extends Serializable {
V get();
}
public interface Cache<K extends CacheKey<? extends Serializable>, V extends CacheValue<? extends Serializable>> {
void put(K key, V value);
}
public class CacheImpl implements Cache<CacheKey<String>, CacheValue<String>> {
@Override
public void put(CacheKey<String> key, CacheValue<String> value) {
// do whatever
}
}
答案 2 :(得分:0)
使用其他答案中建议的通配符绑定的通用类型并不是一个好主意。
如果您这样声明课程:
public interface Cache<K extends CacheKey<?>, V extends CacheValue<?>> {
}
然后,您将永远无法有效地调用键或值上的get()
,因为它们只会返回Serializable
。 Serializable
是一个无用类(实际上与代码中的Object
几乎没有什么不同)。
相反,我只想像这样声明类:
public interface Cache<K extends Serializable, V extends Serializable> {
,然后声明put
方法采用CacheKey<K>
和CacheValue<V>
:
void put(CacheKey<K> key, CacheValue<V> value);
最终,CacheKey<K>
和CacheValue<V>
的所有实现都应该是不可区分的。
如果您真的要强制CacheKey<K>
和CacheValue<V>
属于特定类型,则需要添加更多类型变量:
public interface Cache<
K extends Serializable, CK extends CacheKey<K>,
V extends Serializable, CV extends CacheValue<V>> {
void put(CK key, CV value);
}
但这确实很麻烦,因为无论您在哪里直接使用Cache
类型,都必须携带这4个类型变量。
当然,您可以专门设置接口以隐藏其中一些类型变量:
interface StringKey extends CacheKey<String> {}
interface IntegerValue extends CacheValue<Integer> {}
interface StringIntegerCache extends Cache<String, StringKey, Integer, IntegerValue> {}
,然后仅使用StringIntegerCache
。这样做的用处取决于您的应用程序。