1. 程式人生 > >java generic super/extends (java 泛型中的super/extends)

java generic super/extends (java 泛型中的super/extends)

    @SuppressWarnings("unchecked")
    public V computeIfAbsent(K key, MappingFunction<? super K, ? extends V> mappingFunction) {
        if (key == null || mappingFunction == null)
            throw new NullPointerException();
        return (V)internalComputeIfAbsent(key, mappingFunction);
    }

相比putIfAbsent,這個方法傳入一個計算函式MappingFunction,而不是具體的值。這樣只有在需要的時候呼叫這個MappingFunction建立值,而不是預先建立好。

很有用的一個新方法。但本文的重點不在此,MappingFunction<? super K, ? extends V> 的泛型宣告吸引了我。

為什麼不都使用用extends?super和extends區別在哪?

  • super是宣告下界,extends是宣告上界
  • 聲明瞭下界的泛型容器只能add該泛型引數型別,聲明瞭上界的泛型容器只能get該泛型引數型別
畫圖如下:
不過本文開始的MappingFunction<? super K, ? extends V>,並不是將泛型宣告使用在容器中。
   public static interface MappingFunction<K, V> {
        /**
         * Returns a non-null value for the given key.
         *
         * @param key the (non-null) key
         * @return a non-null value
         */
        V map(K key);
    }

從上面的map中可見,MappingFunction<K,V>中的K在computeIfAbsent中宣告ConcurrentHashMap<K,V>的K為其super 邊界,V宣告ConcurrentHashMap<K,V>的V為其extends邊界。即map方法可以接收ConcurrentHashMap key的父類(包括邊界),返回的value必須是ConcurrentHashMap value的子類(包括邊界)。 假如有ConcurrentHashMap<C1, C2>, computeIfAbsent可以接受MappingFunction<Object, C3>。 C3 map(Object) 的方法可以這樣使用 C2  =  map(C1) 這樣我們總結super和extends的使用,得到一個更廣泛的原則。
  • super用來限制傳入的引數
  • extends使用限制返回的引數