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