泛型 <? 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) :它应该给出错误,因为只应接受超类型的文档。 (3) :它应该作为 RFP 的 super 可以保存 Document 对象。 Difference between <? super T> and <? extends T> in Java

在 Java 1.7 中坚持“它应该像 java 1.7 一样工作”是很奇怪的。 Java 7 根本没有方法引用。

当你写这样的语句时

Supplier<Document> s2 = RFP::new;

你要区分变量的类型,函数的类型,以及实际的实现。你可以很容易地写出等效的

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

由于协变return类型,你也可以写

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

因此变量的类型与函数的类型匹配,而实现 return 是更具体类型的实例。

写的时候

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>。当目标类型有通配符时,仅去除通配符的策略通常会有所帮助,但有时却无济于事。