具有复合键和通配符的Java泛型

时间:2015-01-31 15:03:35

标签: java generics wildcard

我有一对配对,例如

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;
    }
}

现在....我还有一个抽象类:

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类在equals方法中也有通配符。这是我无法实现的,因为JVM在运行时无法解析不同的通配符安排吗?

1 个答案:

答案 0 :(得分:1)

从我的示例代码中可以看出:

1)您的CompositeKeyImplementer必须是通用的。它实现了一个通用接口,您稍后将其称为泛型类型。

public class CompositeKeyImplementer<K1, K2> implements CompositeKeyType<K, V> {
  ...

2)您希望CompositeKeyImplementor<K1, K2>具有K的子类型作为CompositeKeyBasedCreditCardDetailsHolder类中的字段的任何类型参数。

因此,您将CompositeKeyImplementor的调用上的通配符用作类型参数。您不要在CompositeKeyBasedCreditCardDetailsHolder

的泛型类型声明中将它们用作类型参数
public class CompositeKeyBasedCreditCardDetailsHolder<K, V> extends
AbstractBankCardDetailsHolder<K, V> {

    private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;

    // ....... TBC

}

你这样说:

  1. 我声明了类型参数为CompositeKeyBasedCreditCardDetailsHolder的通用K, V
  2. 该类型有一个名为numberProviderPair
  3. 的字段
  4. 哪个本身是通用类型CompositeKeyImplementer<K1, K2>
  5. 实际上它本身可以是任何 CompositeKeyImplementer<K1, K2>,其中类型参数K1, K2K的子类型(包括)
  6. 即。它们的上限由K
  7. 定义的类型参数CompositeKeyBasedCreditCardDetailsHolder限定

    请注意,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,也可能Angelika Langer on wildcard type arguments,因为他们有很多关于通配符用途和信息的信息。