第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

關(guān)于 java.util.function.Function 的 Java 泛型和設(shè)計(jì)的問(wèn)題

關(guān)于 java.util.function.Function 的 Java 泛型和設(shè)計(jì)的問(wèn)題

達(dá)令說(shuō) 2023-06-14 14:43:06
關(guān)于通配符的問(wèn)題例子:Student extends Person? ? Person person = new Person();? ? Student student = new Student();? ? List<? super Student> list = new ArrayList<>();? ? list.add(student); // success? ? list.add(person); // compile error? ? List<? extends Person> list2 = new ArrayList<>();? ? list2.add(person); // compile error? ? list2.add(student);// compile error您正在使用通用通配符。您無(wú)法執(zhí)行添加操作,因?yàn)轭愵愋筒淮_定。你不能添加/放置任何東西(null 除外)&mdash;&mdash;Aniket Thakur官方文檔:通配符從不用作泛型方法調(diào)用、泛型類實(shí)例創(chuàng)建或超類型的類型參數(shù)但是為什么能list.add(student)編譯成功呢?的設(shè)計(jì)java.util.function.Functionpublic interface Function<T, R>{? ? //...? ? default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {? ? ? ? Objects.requireNonNull(before);? ? ? ? return (V v) -> apply(before.apply(v));? ? }}為什么before設(shè)計(jì)為Function<? super V, ? extends T>而不是Function<V,T>當(dāng)返回類型是Function<V,R>并且輸入類型是V?(還可以通過(guò)編譯靈活使用)
查看完整描述

2 回答

?
HUX布斯

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超6個(gè)贊

要理解這些問(wèn)題,您必須了解泛型是如何工作的subtyping(在 Java 中使用關(guān)鍵字明確表示extends)。Andreas 提到了PECS規(guī)則,這是它們?cè)?Java 中的表示。


首先,我想指出上面的代碼可以通過(guò)簡(jiǎn)單的強(qiáng)制轉(zhuǎn)換來(lái)糾正


ArrayList<? super Student> list = new ArrayList<>();

list.add(new Student());

ArrayList<Person> a = (ArrayList<Person>) list; // a covariance

a.add(new Person());

并且編譯和運(yùn)行良好(而不是引發(fā)任何異常)


原因很簡(jiǎn)單,當(dāng)我們有一個(gè)consumer(接受一些對(duì)象并使用它們,例如方法add)時(shí),我們希望它接受我們指定類型no more than(超類)的對(duì)象T,因?yàn)槭褂眠^(guò)程可能需要任何成員(變量,方法等)它想要的類型,我們希望確保該類型T滿足消費(fèi)者所需的所有成員。


相反,producer為我們生成對(duì)象(如get方法)的 a 必須提供no less than指定類型的對(duì)象T,以便我們可以訪問(wèn)T生成的對(duì)象上的任何成員。


covariance這兩個(gè)與稱為和的子類型形式密切相關(guān)contravariance


至于第二個(gè)問(wèn)題,你也可以參考一下的實(shí)現(xiàn)Consumer<T>(比較簡(jiǎn)單):


default Consumer<T> andThen(Consumer<? super T> after) {

  Objects.requireNonNull(after);

  return (T t) -> { accept(t); after.accept(t); };

}

我們需要這個(gè)的原因? super T是:當(dāng)我們使用Consumer方法組合兩個(gè) s時(shí)andThen,假設(shè)前者Consumer采用 type 的對(duì)象T,我們希望后者采用 type 的對(duì)象no more than T,這樣它就不會(huì)嘗試訪問(wèn)任何T不有。


因此,我們不是簡(jiǎn)單地寫(xiě)Consumer<T> afterbut Consumer<? super T> after,而是允許前一個(gè)消費(fèi)者(類型T)與一個(gè)消費(fèi)者結(jié)合,該消費(fèi)者接受一個(gè)不完全是 type 的對(duì)象T,但可能比 小T,方便covariance。這使得以下代碼聽(tīng)起來(lái):


Consumer<Student> stu = (student) -> {};

Consumer<Person> per = (person) -> {};

stu.andThen(per);

出于同樣的考慮,compose類型方法也適用。Function


查看完整回答
反對(duì) 回復(fù) 2023-06-14
?
滄海一幻覺(jué)

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超5個(gè)贊

IMO 這可能是 vanilla Java 中最復(fù)雜的概念。所以讓我們把它分解一下。我將從你的第二個(gè)問(wèn)題開(kāi)始。


Function<T, R>t獲取type 的實(shí)例并返回type 的T實(shí)例。通過(guò)繼承,這意味著您可以提供if類型的實(shí)例,并類似地返回if類型。rRfooFooFoo extends TbarBarBar extends R


作為一個(gè)想要編寫(xiě)一個(gè)靈活的泛型方法的庫(kù)維護(hù)者,很難,實(shí)際上不可能提前知道所有可能與該方法一起使用的擴(kuò)展T和R. 那么我們?nèi)绾尉帉?xiě)處理它們的方法呢?此外,這些實(shí)例具有擴(kuò)展基類的類型這一事實(shí)與我們無(wú)關(guān)。


這就是通配符的用武之地。在方法調(diào)用期間,我們說(shuō)您可以使用滿足所需類范圍的任何類。對(duì)于所討論的方法,我們有兩個(gè)不同的通配符,它們使用上限和下限泛型類型參數(shù):


public interface Function<T, R>{

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before)

現(xiàn)在讓我們說(shuō)我們想利用這個(gè)方法......例如讓我們定義一些基本類:


class Animal{} 

class Dog extends Animal{} 

class Fruit{} 

class Apple extends Fruit{} 

class Fish{} 

class Tuna extends Fish{} 

想象一下我們的函數(shù)和轉(zhuǎn)換定義如下:


Function<Animal, Apple> base = ...;

Function<Fish, Animal> transformation = ...;

我們可以組合這些函數(shù)compose來(lái)創(chuàng)建一個(gè)新函數(shù):


Function<Fish, Apple> composed = base.compose(transformation);

這一切都很好,但現(xiàn)在想象一下,在所需的輸出函數(shù)中,我們實(shí)際上只想用作Tuna輸入。如果我們不使用下界作為我們傳遞給的? super V輸入類型參數(shù),那么我們會(huì)得到一個(gè)編譯器錯(cuò)誤:Functioncompose


default <V> Function<V, R> compose(Function<V, ? extends T> before)

...

Function<Tuna, Apple> composed = base.compose(transformation);

> Incompatible types: 

> Found: Function<Fish, Apple>, required: Function<Tuna, Apple>

發(fā)生這種情況是因?yàn)檎{(diào)用的返回類型compose指定V為,Tuna而transformation另一方面指定其“ V”為Fish。所以現(xiàn)在當(dāng)我們嘗試傳遞transformation給compose編譯器時(shí)需要transformation接受 aTuna作為其V當(dāng)然Tuna不完全匹配Fish。


另一方面,代碼的原始版本 ( ? super V) 允許我們將其視為V下界(即它允許“逆變”與“不變” V)。編譯器不會(huì)遇到Tuna和之間的不匹配,而是Fish能夠成功應(yīng)用? super V計(jì)算結(jié)果為 的下限檢查Fish super Tuna,自 以來(lái)為真Tuna extends Fish。


對(duì)于另一種情況,假設(shè)我們的調(diào)用定義為:


Function<Animal, Apple> base = ...;

Function<Fish, Dog> transformation = ...;

Function<Fish, Apple> composed = base.compose(transformation);

如果我們沒(méi)有通配符,? extends T那么我們會(huì)得到另一個(gè)錯(cuò)誤:


default <V> Function<V, R> compose(Function<? super V, T> before)

Function<Fish, Apple> composed = base.compose(transformation);

// error converting transformation from

//    Function<Fish, Dog> to Function<Fish, Animal>

通配符允許它按照is resolved to 的? extends T方式工作,并且通配符 resolves to可以滿足約束條件。TAnimalDogDog extends Animal


對(duì)于你的第一個(gè)問(wèn)題;這些邊界實(shí)際上只在方法調(diào)用的上下文中起作用。在該方法的過(guò)程中,通配符將被解析為實(shí)際類型,就像? super V被解析為Fish和? extends T被解析為一樣Dog。如果沒(méi)有來(lái)自泛型簽名的信息,我們將無(wú)法讓編譯器知道可以在類型的方法上使用哪個(gè)類,因此不允許使用任何類。


查看完整回答
反對(duì) 回復(fù) 2023-06-14
  • 2 回答
  • 0 關(guān)注
  • 146 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)