Java collections — polymorphic access to elements

后端 未结 3 1968
余生分开走
余生分开走 2021-01-28 08:03

I have a LinkedHashSet of values of ThisType. ThisType is implementing the interface ThatType.

I ne

相关标签:
3条回答
  • 2021-01-28 08:30

    When you declare a wildcard bounded type argument as in

    LinkedHashMap<Integer, ? extends ThatType> theMap = new LinkedHashMap<>();
    

    you are telling the compiler that the type argument can be any class that is a sub type of ThatType. Imagine this case

    LinkedHashMap<Integer, ? extends ThatType> theMap = getLinkedHashMap();
    

    where getLinkedHashMap() is defined as

    public LinkedHashMap<Integer, OtherType /* which implements ThatType */> getLinkedHashMap();
    

    The previous assignment would work because OtherType is a sub type of ThatType. However, you could not then expect

    ThisType a = theMap.get(key);
    

    to work. Because of the wildcard, all you know is that the map definitely contains ThatType instances (called the upper bound), but they could be of type OtherType or ThatType (or other sub type of ThatType). At most you could do

    ThisType a = (ThisType) theMap.get(key);
    

    casting the return value, but then you are opening yourself up to ClassCastException.

    Similarly, you cannot call put() with anything other than than null.

    theMap.put(someInt, null); // will compile
    theMap.put(someInt, new ThisType()); // will not compile
    theMap.put(someInt, new OtherType()); // will not compile
    

    The compiler doesn't let you add anything because it can't guarantee what the map contains, again because of the wildcard bound. But null can be used because

    The null reference can always undergo a widening reference conversion to any reference type.

    So null is a valid argument because it is the lower bound of the wildcard.


    You're in a special situation where, it seems, your method creates the LinkedHashMap internally and you know what you will be passing to it. Therefore you can do the following

    public static LinkedHashMap<Integer, ThatType> getTheSet(int[] intArray) {
        LinkedHashMap<Integer, ThatType> theMap = new LinkedHashMap<>();
    
        for (Integer key : intArray) {
            ThisType a = new ThisType();
            if (theMap.containsKey(key)) {
                a = (ThisType) theMap.get(key); // cast it because you know they will definitely be `ThisType` references
                a.doStuff();
            } else {
                a.doOtherStuff();
            }
            theMap.put(key, a);
        }
    
        return theMap;
    }
    

    Since ThisType is a sub type of ThatType, you can put instances of ThisType into the map. You need to be careful how you then use this method's returned value. All the compiler knows about the return value is that it contains ThatType references. It doesn't know that they are actually ThisType.

    0 讨论(0)
  • 2021-01-28 08:31

    You need the wildcard of Set<? super ThisType>. Look at following example

    public static void main(String[] args) {
        Set<ThatType> set=new LinkedHashSet<>();
        Set<ThisType> set2=new LinkedHashSet<>();
    
        someFunction(set);
        someFunction(set2);
    }
    
    static void someFunction(Set<? super ThisType> set) {
    
    }
    
    class ThisType implements ThatType{
    
    }
    interface ThatType{
    
    }
    
    0 讨论(0)
  • 2021-01-28 08:49

    I think what you want is to use wildcards.

     LinkedHashSet<? extends ThatType> someFunction(LinkedHashSet<? extends ThatType> set) {
          return set;
     }
    

    As has been explained elsewhere LinkedHashSet<ThisType> is not a subclass of LinkedHashSet<ThatType>, since LinkedHashSet<ThisType> can't accept ThatType objects.

    The wildcard in LinkedHashSet<? extends ThatType> means a LinkedHastSet of some class (not sure what) that extends ThatType.

    Though you may want to consider using this:

     Set<? extends ThatType> someFunction(Set<? extends ThatType> set) {
          return set;
     }
    
    0 讨论(0)
提交回复
热议问题