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

}

你说的是:

  1. 我正在声明一个带有类型参数 K, V 的泛型 CompositeKeyBasedCreditCardDetailsHolder
  2. 该类型有一个名为 numberProviderPair
  3. 的字段
  4. 它本身就是泛型CompositeKeyImplementer<K1, K2>
  5. 事实上它本身可以是 any CompositeKeyImplementer<K1, K2> 其中类型参数 K1, K2K[ 的子类型(包括) =57=]
  6. 即它们的上限由 CompositeKeyBasedCreditCardDetailsHolder
  7. 定义的类型参数 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,因为他们有很多关于通配符的用途和使用方式的信息。