简体   繁体   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();
        }

    }

Problem in (1) (2) & (3) is that, it should work as java 1.7 (1): it should give error as only Document type should be accepted. (1) (2) & (3) 中的问题是,它应该像 java 1.7 (1) 一样工作:它应该给出错误,因为应该只接受文档类型。 (2): it should give error as only super type of Document should be accepted. (2):它应该给出错误,因为应该只接受超类型的 Document。 (3): it should be working as super of RFP can hold Document object. (3):它应该作为RFP的super可以持有文件object。 Difference between <? <? 之间的区别super T> and <? 超级 T> 和 <? extends T> in Java 在 Java 中扩展 T>

It's weird to insist on “it should work as java 1.7”, when in Java 1.7 resp.在 Java 1.7 和 Java 1.7 中坚持“它应该像 java 1.7 一样工作”是很奇怪的。 Java 7 there were no method references at all. Java 7 根本没有方法引用。

When you write a statement like当你写一个像

Supplier<Document> s2 = RFP::new;

You have to make a distinction between the type of the variable, the type of the function, and the actual implementation.您必须区分变量的类型、function 的类型和实际实现。 You can easily write the equivalent您可以轻松编写等效的

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

due to covariant return types, you can also write由于协变返回类型,您还可以编写

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

So the type of the variable matches the type of the function, whereas the implementation returns an instance of a more specific type.所以变量的类型匹配 function 的类型,而实现返回一个更具体类型的实例。

When you write当你写

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)

the type of the function will differ. function 的类型会有所不同。 You can not write new Supplier<? extends Document>() { … }你不能写new Supplier<? extends Document>() { … } new Supplier<? extends Document>() { … } nor new Supplier<? super Document>() { … } new Supplier<? extends Document>() { … }也不是new Supplier<? super Document>() { … } new Supplier<? super Document>() { … } and so the compiler will infer a type that can be instantiated, which simply is the target type type without ? extends new Supplier<? super Document>() { … }所以编译器会推断出一个可以实例化的类型,它只是没有? extends ? extends or ? super ? extends? super ? super . ? super So it's equivalent to所以它相当于

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)

which are valid instantiations (like in the first block), followed by legal assignments.它们是有效的实例化(如在第一个块中),然后是合法的赋值。

The problem with问题与

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

lies exactly in the type inference logic described above.正是在上面描述的类型推断逻辑中。 The type inference will use the type without ? super类型推断将使用不带? super ? super , and (Supplier<RFP>)Document::new is not valid. ? super(Supplier<RFP>)Document::new无效。 So here, we have to provide an explicit type to make it valid:所以在这里,我们必须提供一个显式类型来使其有效:

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

which follows the same pattern as the second block.它遵循与第二块相同的模式。
You can not implement a Supplier<? super RFP>你不能实现一个Supplier<? super RFP> Supplier<? super RFP> . Supplier<? super RFP> . You can implement a supplier like Supplier<Document> which is assignable to Supplier<? super RFP>您可以实现像Supplier<Document>这样可分配给Supplier<? super RFP> Supplier<? super RFP> . Supplier<? super RFP> . When the target type has wildcards, the strategy to just strip off the wildcards often helps but sometimes doesn't.当目标类型有通配符时,去掉通配符的策略通常会有所帮助,但有时不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM