簡體   English   中英

Generics<!--? super--> 通配符在 java 1.8 中不起作用,帶有方法參考或 lambda

[英]Generics <? super> wildcard not working in java 1.8 with method reference or lambda

    package com.test.lambda;

    import java.util.function.Supplier;

    class Document {
        void printAuthor() {
            System.out.println("Document-Author");
        }
    }

    class RFP extends Document {
        @Override
        void printAuthor() {
            System.out.println("RFP-Author");
        }
    }

    public class TestLambda1 {
        public static void function21() {
            Supplier<Document> s1 = Document::new; // working
            Supplier<Document> s2 = RFP::new; // (1)

            Supplier<? extends Document> s3 = Document::new; // working
            Supplier<? extends Document> s4 = RFP::new; // working

            Supplier<? super Document> s5 = Document::new; // working
            Supplier<? super Document> s6 = RFP::new; // (2)

            Supplier<? super RFP> s7 = Document::new; // (3)
            Supplier<? super RFP> s8 = RFP::new; // working

        }

        public static void main(String[] args) throws Exception {
            function21();
        }

    }

(1) (2) & (3) 中的問題是,它應該像 java 1.7 (1) 一樣工作:它應該給出錯誤,因為應該只接受文檔類型。 (2):它應該給出錯誤,因為應該只接受超類型的 Document。 (3):它應該作為RFP的super可以持有文件object。 <? 之間的區別 超級 T> 和 <? 在 Java 中擴展 T>

在 Java 1.7 和 Java 1.7 中堅持“它應該像 java 1.7 一樣工作”是很奇怪的。 Java 7 根本沒有方法引用。

當你寫一個像

Supplier<Document> s2 = RFP::new;

您必須區分變量的類型、function 的類型和實際實現。 您可以輕松編寫等效的

Supplier<Document> s2 = new Supplier<Document>() {
    public Document get() {
        return new RFP();
    }
}; // (1)

由於協變返回類型,您還可以編寫

Supplier<Document> s2 = new Supplier<Document>() {
    public RFP get() {
        return new RFP();
    }
}; // (1)

所以變量的類型匹配 function 的類型,而實現返回一個更具體類型的實例。

當你寫

Supplier<? extends Document> s3 = Document::new; // working
Supplier<? extends Document> s4 = RFP::new; // working

Supplier<? super Document> s5 = Document::new; // working
Supplier<? super Document> s6 = RFP::new; // (2)

function 的類型會有所不同。 你不能寫new Supplier<? extends Document>() { … } new Supplier<? extends Document>() { … }也不是new Supplier<? super Document>() { … } new Supplier<? super Document>() { … }所以編譯器會推斷出一個可以實例化的類型,它只是沒有? extends ? extends? super ? super 所以它相當於

Supplier<? extends Document> s3 = (Supplier<Document>)Document::new; // working
Supplier<? extends Document> s4 = (Supplier<Document>)RFP::new; // working

Supplier<? super Document> s5 = (Supplier<Document>)Document::new; // working
Supplier<? super Document> s6 = (Supplier<Document>)RFP::new; // (2) just like (1)

它們是有效的實例化(如在第一個塊中),然后是合法的賦值。

問題與

Supplier<? super RFP> s7 = Document::new; // (3)

正是在上面描述的類型推斷邏輯中。 類型推斷將使用不帶? super ? super(Supplier<RFP>)Document::new無效。 所以在這里,我們必須提供一個顯式類型來使其有效:

Supplier<? super RFP> s7 = (Supplier<Document>)Document::new; // (3)

它遵循與第二塊相同的模式。
你不能實現一個Supplier<? super RFP> Supplier<? super RFP> . 您可以實現像Supplier<Document>這樣可分配給Supplier<? super RFP> Supplier<? super RFP> . 當目標類型有通配符時,去掉通配符的策略通常會有所幫助,但有時不會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM