Avoiding Returning Wildcard Types

后端 未结 4 1570
暗喜
暗喜 2021-02-08 10:26

I have a class with a collection of Wildcard Types that is a singleton, something like:

public ObliviousClass{

    private static final ObliviousClass INSTANCE          


        
4条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-08 10:50

    Your ObliviousClass, by design, doesn't know the parameterized type of the item it holds. So to be type safe, you should avoid such design :-\

    But if you want to keep it, first things is that you will have to cast. There is no way out of this. But the way you do it is very error prone. For example:

    oc.put(k1, intType);
    oc.put(k2, strType);
    Type tint = oc.get(k1, Integer.class)
    Type  tstr = oc.get(k1, String.class)  // typo in k2: compile fine
    

    And worst, due to type erasure, it will fail at runtime only once you actually use tstr, not when you get it from ObliviousClass.

    So you can improve safety by tracking the parameterized type in some other way. For example, you could associate the key to the type, not losing it:

    @Value // lombok
    class Key {
        private int index;
    }
    
    class Type {}
    
    class ObliviousClass {
    
        // side note: static final can be public safely
        public static final ObliviousClass instance = new ObliviousClass();
    
        private List> map = new ArrayList<>();
    
        public  Key appendType(Type type){
            // here, I found it nicer that obliviousClass generates and return the key
            // otherwise use:  "public  void appendType(key key, Type type)"
            // that binds parametrized type of both key and type arguments
            map.add(type);
            return new Key<>(map.size() - 1);
        }
    
    
        public  Type get(Key key){
            return (Type) map.get(key.index);
        }
    }
    

    Then you can use it such as:

        Type intType = new Type<>();
        Type  strType = new Type<>();
        Key k1 = ObliviousClass.instance.appendType(intType);
        Key  k2 = ObliviousClass.instance.appendType(strType);
    
        Type t1 = ObliviousClass.instance.get(k1);
        Type  t2 = ObliviousClass.instance.get(k2);
        Type  t3 = ObliviousClass.instance.get(k1); // won't compile
    

提交回复
热议问题