好的軟件的作用是讓復(fù)雜的東西看起來(lái)簡(jiǎn)單座韵。
java中協(xié)變跟逆變是對(duì)泛型類的繼承關(guān)系的表述.
如:
List<Number>
和List<Integer>
之間是沒(méi)有繼承關(guān)系的.
但是直觀上會(huì)覺(jué)得, Integer
是Number
的子類, 所以List<Integer>
應(yīng)是List<Number>
的子類.
如果想要這種效果, 就要用協(xié)變.
List<? extends Number>
這樣 List<Integer>
就能成為L(zhǎng)ist<? extends Number> 子類, 也就是可以賦值
List<Integer>b = new ArrayList<>();
List<? extends Number> a = b;
這里如果你想要相反的效果, 則用逆變,List<? super Number>
這樣繼承關(guān)系就會(huì)相反.
那么什么時(shí)候用協(xié)變,逆變?
協(xié)變主要是用在函數(shù)的返回值上,逆變用在函數(shù)參數(shù)上,這樣的規(guī)則也就能遵循里氏替換原則
.
如Function
, 在這里R
作為函數(shù)的返回值, 所以這個(gè)泛型要協(xié)變, 而T
用在函數(shù)的參數(shù)上所以要用逆變
Function<? super Dog,? extends Animal> f1;
這里舉個(gè)例子
假設(shè)有以下繼承關(guān)系:
車 > 轎車 > 標(biāo)準(zhǔn)轎車 > 高級(jí)轎車
現(xiàn)在有一個(gè)人聲稱自己能修理所有的標(biāo)準(zhǔn)轎車, 所以發(fā)出了以下公告:
修理(List<標(biāo)準(zhǔn)轎車> cars)
假設(shè)我現(xiàn)在有List<轎車>
和 List<高級(jí)轎車>
那么這個(gè)人到底能修理哪個(gè)呢? 從上面的函數(shù)聲明來(lái)看都不可以.
再來(lái)看看這個(gè)人的聲明
他說(shuō)能夠修理所有標(biāo)準(zhǔn)轎車
那么因?yàn)闃?biāo)準(zhǔn)轎車擴(kuò)展了轎車, 所以如果能夠修理標(biāo)準(zhǔn)轎車, 那么應(yīng)當(dāng)可以修理轎車
所以這個(gè)函數(shù)應(yīng)當(dāng)可以接受所有標(biāo)準(zhǔn)轎車
的父類
也就是說(shuō) List<轎車>
能夠傳入 以List<標(biāo)準(zhǔn)轎車>
為參數(shù)的函數(shù)
換句話說(shuō) List<轎車>
是List<標(biāo)準(zhǔn)轎車>
的子類, 這樣才能傳入?yún)?shù)
所以上面的公告要用逆變, 改成如下:
修理(List<? super 標(biāo)準(zhǔn)轎車> cars)
也許也不會(huì)有人想把自己的高級(jí)轎車交給這家伙.
以此類推, 函數(shù)的返回值應(yīng)當(dāng)用協(xié)變, 這樣既能滿足里氏替換原則
了