我对Java 8的类型推断感到困惑。以下代码:
private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
toIterator() {
return Iterable<? extends T>::iterator;
}
打破编译错误
error: incompatible types: invalid method reference
return Iterable<? extends T>::iterator;
^
method iterator in interface Iterable<T#2> cannot be applied to given types
required: no arguments
found: Iterable<? extends T#1>
reason: actual and formal argument lists differ in length
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>toIterator()
T#2 extends Object declared in interface Iterable
而删除显式泛型
private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
toIterator() {
return Iterable::iterator;
}
起作用,老派匿名内部班级也是如此
private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
toIterator() {
return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
@Override
public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
return iterable.iterator();
}
};
}
有人可以建议可能会发生什么吗?
答案 0 :(得分:5)
使用<? extends T>
是错误的,因为对于具有显式类型参数的通用调用,您必须指定完整类型,而不是通配符类型。
如果您只是使用
private static <T> Function<Iterable<? extends T>, Iterator<? extends T>>
toIterator() {
return Iterable::iterator;
}
Java会为你推断出类型。
解决方案是:
private static <T> Function<Iterable<T>, Iterator<? extends T>> toIterator() {
return Iterable<T>::iterator;
}
虽然不清楚将Function
的返回类型扩展到? extends T
的优势是什么。对于实际用途,
private static <T> Function<Iterable<T>, Iterator<T>> toIterator() {
return Iterable<T>::iterator;
}
将是最有用的方法签名。为此,推断Iterable::iterator
仍然有效。
关于编译器错误消息,这似乎只是错误报告中的错误,当对非static
方法的方法引用具有类型不匹配时,该错误始终适用。它甚至可以通过简单的声明再现:
Consumer<Object> c=String::getClass;
产生错误消息:
error: incompatible types: invalid method reference
Consumer<Object> c=String::getClass;
^
method getClass in class Object cannot be applied to given types
required: no arguments
found: Object
reason: actual and formal argument lists differ in length
请注意,对static
方法的引用会收到正确的错误消息:
Consumer<Object> c=Class::forName;
产生
error: incompatible types: invalid method reference
Consumer<Object> c=Class::forName;
^
incompatible types: Object cannot be converted to String