【发布时间】:2018-05-03 09:00:34
【问题描述】:
我有两个泛型方法,旨在强制调用者提供匹配类型的参数:
private <T> void compareValues(Supplier<T> supplier, T value) {
System.out.println(supplier.get() == value);
}
private <T> void setValue(Consumer<T> consumer, T value) {
consumer.accept(value);
}
但是,在调用它们时,编译器对允许作为参数传递的内容有不同的解释:
compareValues(this::getString, "Foo"); // Valid, as expected
compareValues(this::getInt, "Foo"); // Valid, but compiler should raise error
compareValues(this::getString, 1); // Valid, but compiler should raise error
setValue(this::setString, "Foo"); // Valid, as expected
setValue(this::setInt, "Foo"); // Type mismatch, as expected
setValue(this::setString, 1); // Type mismatch, as expected
private String getString() {
return "Foo";
}
private int getInt() {
return 1;
}
private void setString(String string) {
}
private void setInt(int integer) {
}
怎么会?编译器是否过于笨拙而无法正确推断此处的类型,或者这是类型系统的一个特性?如果是这样,导致这种行为的规则是什么?另外,如果可能的话,如何在不添加人工参数的情况下创建 compareValues 的“类型安全”版本?
请注意,提供的方法仅包含一个虚拟实现,并不反映我实际代码库中的代码。这里只关注方法调用。
【问题讨论】:
-
编译器推断出
compareValues()参数的最常见类型,因此对于第二次和第三次compareValues()调用,结果是Serializable & Comparable<? extends Serializable & Comparable<?>>。 -
另外,请注意您可能应该使用
equals。 -
@VladimirVagaytsev 在哪些情况下编译器会这样做?
-
@xagaffar 在每种情况下,编译器都会尝试找到最常见的类型,如果找不到它只会选择
Object
标签: java generics lambda java-8