Reputation: 6862
I have a pair interface e.g.
public interface CompositeKeyType<K1, K2> {
public K1 getKey1();
public K2 getKey2();
}
And an implementation:
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;
}
}
Now....I also have an abstract 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);
}
}
Which I am generalising here (it is coming up with errors):
public class CompositeKeyBasedCreditCardDetailsHolder<? extends K, ? extends V> extends
AbstractBankCardDetailsHolder<? extends K, ? extends V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
I was under the impression that ? wildcard means ?TypeUnknown? and it will resolve the types @Runtime. However, I notices whilsts writing this questiont that my CompositeKeyImplementer.java
class has got wildcards in the equals
method too. Is this something that I won't be able to achieve because JVM cannot resolve the different wildcard arrangements such as this one during runtime?
Upvotes: 0
Views: 173
Reputation: 19171
From what I can work out from your sample code:
1) Your CompositeKeyImplementer
needs to be generic. It implements a generic interface, and you later refer to it as a generic type.
public class CompositeKeyImplementer<K1, K2> implements CompositeKeyType<K, V> {
...
2) You want to have a CompositeKeyImplementor<K1, K2>
with any type arguments that are subtypes of K
as a field in your CompositeKeyBasedCreditCardDetailsHolder
class.
Therefore you use the wildcards on invocation of that CompositeKeyImplementor
as type arguments. You don't use them as type parameters in the generic type declaration for CompositeKeyBasedCreditCardDetailsHolder
public class CompositeKeyBasedCreditCardDetailsHolder<K, V> extends
AbstractBankCardDetailsHolder<K, V> {
private CompositeKeyImplementer<? extends K, ? extends K> numberProviderPair;
// ....... TBC
}
With this you are saying:
CompositeKeyBasedCreditCardDetailsHolder
with type parameters K, V
.numberProviderPair
CompositeKeyImplementer<K1, K2>
CompositeKeyImplementer<K1, K2>
where the type parameters K1, K2
are a subtype (inclusive) of K
K
defined by CompositeKeyBasedCreditCardDetailsHolder
Note that the type arguments for K1, K2
are not restricted to the same type. For example: this is possible:
// 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);
I recommend (re-)reading the java tutorials on wildcards, and possibly also Angelika Langer on wildcard type arguments as they have a lot of information on what wildcards are used for and how.
Upvotes: 1