java generic super/extends (java 泛型中的super/extends)
阿新 • • 發佈:2019-01-01
@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使用限制返回的引數