Java 具有复合键和通配符的泛型
Java Generics with Composite Key and Wildcards
我有一对接口,例如
public interface CompositeKeyType<K1, K2> {
public K1 getKey1();
public K2 getKey2();
}
和一个实现:
package com.bcsg.creditcardrecords;
public class CompositeKeyImplementer<K1, K2> implements
CompositeKeyType<K1, K2> {
private K1 key1;
private K2 key2;
public CompositeKeyImplementer() {
this.key1 = null;
this.key2 = null;
}
public CompositeKeyImplementer(K1 key1, K2 key2) throws IllegalArgumentException {
if (key1.equals(key2)){
throw new IllegalArgumentException("both keys cannot be equal");
}
this.key1 = key1;
this.key2 = key2;
}
@Override
public K1 getKey1() {
return this.key1;
}
@Override
public K2 getKey2() {
return this.key2;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CompositeKeyImplementer<?, ?>)) {
return false;
}
if (!(((CompositeKeyImplementer<?, ?>) obj).getKey1().equals(this.key1))
|| !(((CompositeKeyImplementer<?, ?>) obj).getKey2()
.equals(this.key2))) {
return false;
}
return true;
}
}
现在....我也有一个摘要class:
public abstract class AbstractBankCardDetailsHolder<K, V> {
private NavigableMap<K, V> cardData;
public AbstractBankCardDetailsHolder() {
cardData = new TreeMap<K, V>();
}
public AbstractBankCardDetailsHolder(K key, V value){
cardData.put(key, value);
}
public NavigableMap<K, V> getCardData(){
return this.cardData;
}
public void setCardData(NavigableMap<K,V> cadData){
this.cardData.clear();
this.cardData.putAll(cardData);
}
}
我在这里概括的(它会出现错误):
public class CompositeKeyBasedCreditCardDetailsHolder<? extends K, ? extends V> extends
AbstractBankCardDetailsHolder<? extends K, ? extends V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
我的印象是?通配符意味着?TypeUnknown?它将解析@Runtime 类型。但是,我注意到在写这个问题时我的 CompositeKeyImplementer.java
class 在 equals
方法中也有通配符。这是我无法实现的事情吗,因为 JVM 无法在运行时解析不同的通配符安排,例如这个?
根据您的示例代码我可以得出的结果:
1) 您的 CompositeKeyImplementer
需要通用。它实现了一个泛型接口,您稍后将其称为泛型类型。
public class CompositeKeyImplementer<K1, K2> implements CompositeKeyType<K, V> {
...
2) 您希望 CompositeKeyImplementor<K1, K2>
具有作为 K
子类型的任何类型参数作为 CompositeKeyBasedCreditCardDetailsHolder
class 中的字段。
因此,您在 CompositeKeyImplementor
的调用 中使用通配符 作为 类型参数 。您不要在 CompositeKeyBasedCreditCardDetailsHolder
的泛型类型声明中将它们用作 类型参数
public class CompositeKeyBasedCreditCardDetailsHolder<K, V> extends
AbstractBankCardDetailsHolder<K, V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
你说的是:
- 我正在声明一个带有类型参数
K, V
的泛型 CompositeKeyBasedCreditCardDetailsHolder
。
- 该类型有一个名为
numberProviderPair
的字段
- 它本身就是泛型
CompositeKeyImplementer<K1, K2>
- 事实上它本身可以是 any
CompositeKeyImplementer<K1, K2>
其中类型参数 K1, K2
是 K
[ 的子类型(包括) =57=]
- 即它们的上限由
CompositeKeyBasedCreditCardDetailsHolder
定义的类型参数 K
请注意,K1, K2
的类型参数不限于同一类型。例如:这是可能的:
// note the arguments for K1, K2. Both extend Number
CompositeKeyImplementer<Integer, Double> cki =
new CompositeKeyImplementer<Integer, Double>();
// note the argument for K is Number
CompositeKeyBasedCreditCardDetailsHolder<Number, String> cdh =
new CompositeKeyBasedCreditCardDetailsHolder<Number, String>(cki);
我建议(重新)阅读 the java tutorials on wildcards, and possibly also Angelika Langer on wildcard type arguments,因为他们有很多关于通配符的用途和使用方式的信息。
我有一对接口,例如
public interface CompositeKeyType<K1, K2> {
public K1 getKey1();
public K2 getKey2();
}
和一个实现:
package com.bcsg.creditcardrecords;
public class CompositeKeyImplementer<K1, K2> implements
CompositeKeyType<K1, K2> {
private K1 key1;
private K2 key2;
public CompositeKeyImplementer() {
this.key1 = null;
this.key2 = null;
}
public CompositeKeyImplementer(K1 key1, K2 key2) throws IllegalArgumentException {
if (key1.equals(key2)){
throw new IllegalArgumentException("both keys cannot be equal");
}
this.key1 = key1;
this.key2 = key2;
}
@Override
public K1 getKey1() {
return this.key1;
}
@Override
public K2 getKey2() {
return this.key2;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CompositeKeyImplementer<?, ?>)) {
return false;
}
if (!(((CompositeKeyImplementer<?, ?>) obj).getKey1().equals(this.key1))
|| !(((CompositeKeyImplementer<?, ?>) obj).getKey2()
.equals(this.key2))) {
return false;
}
return true;
}
}
现在....我也有一个摘要class:
public abstract class AbstractBankCardDetailsHolder<K, V> {
private NavigableMap<K, V> cardData;
public AbstractBankCardDetailsHolder() {
cardData = new TreeMap<K, V>();
}
public AbstractBankCardDetailsHolder(K key, V value){
cardData.put(key, value);
}
public NavigableMap<K, V> getCardData(){
return this.cardData;
}
public void setCardData(NavigableMap<K,V> cadData){
this.cardData.clear();
this.cardData.putAll(cardData);
}
}
我在这里概括的(它会出现错误):
public class CompositeKeyBasedCreditCardDetailsHolder<? extends K, ? extends V> extends
AbstractBankCardDetailsHolder<? extends K, ? extends V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
我的印象是?通配符意味着?TypeUnknown?它将解析@Runtime 类型。但是,我注意到在写这个问题时我的 CompositeKeyImplementer.java
class 在 equals
方法中也有通配符。这是我无法实现的事情吗,因为 JVM 无法在运行时解析不同的通配符安排,例如这个?
根据您的示例代码我可以得出的结果:
1) 您的 CompositeKeyImplementer
需要通用。它实现了一个泛型接口,您稍后将其称为泛型类型。
public class CompositeKeyImplementer<K1, K2> implements CompositeKeyType<K, V> {
...
2) 您希望 CompositeKeyImplementor<K1, K2>
具有作为 K
子类型的任何类型参数作为 CompositeKeyBasedCreditCardDetailsHolder
class 中的字段。
因此,您在 CompositeKeyImplementor
的调用 中使用通配符 作为 类型参数 。您不要在 CompositeKeyBasedCreditCardDetailsHolder
public class CompositeKeyBasedCreditCardDetailsHolder<K, V> extends
AbstractBankCardDetailsHolder<K, V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
你说的是:
- 我正在声明一个带有类型参数
K, V
的泛型CompositeKeyBasedCreditCardDetailsHolder
。 - 该类型有一个名为
numberProviderPair
的字段
- 它本身就是泛型
CompositeKeyImplementer<K1, K2>
- 事实上它本身可以是 any
CompositeKeyImplementer<K1, K2>
其中类型参数K1, K2
是K
[ 的子类型(包括) =57=] - 即它们的上限由
CompositeKeyBasedCreditCardDetailsHolder
定义的类型参数
K
请注意,K1, K2
的类型参数不限于同一类型。例如:这是可能的:
// note the arguments for K1, K2. Both extend Number
CompositeKeyImplementer<Integer, Double> cki =
new CompositeKeyImplementer<Integer, Double>();
// note the argument for K is Number
CompositeKeyBasedCreditCardDetailsHolder<Number, String> cdh =
new CompositeKeyBasedCreditCardDetailsHolder<Number, String>(cki);
我建议(重新)阅读 the java tutorials on wildcards, and possibly also Angelika Langer on wildcard type arguments,因为他们有很多关于通配符的用途和使用方式的信息。