ジェネリック<?スーパー>ワイルドカードのメソッド参照やラムダを使用してJava 1.8で動作しません

ashishjaintech:
    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)文書の唯一のスーパータイプが受け入れなければならないように、それがエラーを与えるべきです。(3):それはDocumentオブジェクトを保持することができますRFPのスーパーとして作業する必要があります。違い<?スーパーT>と<?TはJavaで>拡張します

ホルガー:

それはときに、Java 1.7 RESPで、「それは、Java 1.7のように動作するはずです」を主張する奇妙です。Javaの7全くメソッドの参照がありませんでした。

あなたのような文を書くとき

Supplier<Document> s2 = RFP::new;

あなたは、変数の型、関数の型、および実際の実装の区別をしなければなりません。あなたは簡単に相当するものを書くことができます

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)

実装は、より特定の型のインスタンスを返し、一方、変数の型に、機能の種類と一致しています。

あなたが書くとき

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)

関数の型が異なります。あなたは書くことはできませんnew Supplier<? extends Document>() { … }new Supplier<? super Document>() { … }ので、コンパイラは、単純にすることなく、ターゲット型のタイプである、インスタンス化することができるタイプを推測します? extends? 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と、(Supplier<RFP>)Document::new有効ではありません。そこでここでは、我々はそれが有効にするために明示的な型を提供する必要があります。

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

その第二のブロックと同じパターンに従います。
あなたは、実装することはできませんSupplier<? super RFP>あなたは次のようにサプライヤー実装することができますSupplier<Document>に割り当て可能であるがSupplier<? super RFP>ターゲット・タイプは、ワイルドカードを持っている場合は、ワイルドカードオフだけでストリップへの戦略は、多くの場合に役立ちますが、時にはません。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=335649&siteId=1