Ism*_*awi 12 java eclipse generics java-8
我有一段代码可以在java 7下编译,但不是在java 8下编译.这是一个独立的再现示例(我已经采用了真正的代码来展示这个问题并且删除了所有的实现):
import java.util.Iterator;
class ASTNode<T extends ASTNode> implements Iterable<T> {
@Override public Iterator<T> iterator() { return null; }
}
class List<T extends ASTNode> extends ASTNode<T> {}
interface Function<F, T> {}
class Iterables {
public static <F,T> Iterable<T> transform(
Iterable<F> fromIterable, Function<? super F, ? extends T> function) { return null; }
}
class AstFunctions {
public static <T extends ASTNode<?>> Function<T, String> prettyPrint() { return null; }
}
public class Main {
public static void test() {
List<? extends ASTNode<?>> list = null;
Iterables.transform(list, AstFunctions.prettyPrint());
}
}
Run Code Online (Sandbox Code Playgroud)
见证人:
$ javac -version
javac 1.8.0_05
$ javac -source 1.7 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
$ javac -source 1.8 Main.java
Main.java:23: error: method transform in class Iterables cannot be applied to given types;
Iterables.transform(list, AstFunctions.prettyPrint());
^
required: Iterable<F>,Function<? super F,? extends T#1>
found: List<CAP#1>,Function<ASTNode<?>,String>
reason: cannot infer type-variable(s) F,T#1,T#2
(argument mismatch; Function<CAP#1,String> cannot be converted to Function<? super CAP#1,? extends String>)
where F,T#1,T#2 are type-variables:
F extends Object declared in method <F,T#1>transform(Iterable<F>,Function<? super F,? extends T#1>)
T#1 extends Object declared in method <F,T#1>transform(Iterable<F>,Function<? super F,? extends T#1>)
T#2 extends ASTNode<?> declared in method <T#2>prettyPrint()
where CAP#1 is a fresh type-variable:
CAP#1 extends ASTNode<?> from capture of ? extends ASTNode<?>
1 error
Run Code Online (Sandbox Code Playgroud)
(或许值得注意的是,Eclipse配置为1.8兼容性,此代码没有问题).
这是编译器错误吗?如果没有,那么假设我被允许改变AstFunctions
和Main
(但不包括ASTNode
,List
,Function
,或Iterables
),我怎样才能使此代码编译?我还想了解,如果可能的话,对Java 8类型系统的哪些更改会导致此代码无法编译.
这在最后一个javac 9的当前版本的编译器中不是问题.在进行任何其他考虑之前,应根据此版本检查任何明显的错误.
对于最后一个javac8代码,要检查的存储库是最后一个javac 8.此问题已在该存储库中修复.JDK-8033718的补丁修复了该问题
更新:请参阅其他答案 - 这是 javac 中的一个错误,现已修复。
感觉这不应该编译,并且 Java 8 表现出正确的行为:
Iterables.transform
需要一个Iterable<F> fromIterable
and Function<? super F...
,所以第一个泛型类型Function
需要是泛型类型的超类Iterable
F1 == ? extends ASTNode<?>
,返回的 Function 的第一个类型prettyPrint
是F2 == T extends ASTNode<?>
我认为没有办法证明F2是F1的超类型。例如,假设您有:
class A1 extends ASTNode<A1> {}
class A2 extends ASTNode<A2> {}
Run Code Online (Sandbox Code Playgroud)
并在你的主要内容中:
List<? extends ASTNode<?>> list = new List<A1>(); //F1 = A1
Run Code Online (Sandbox Code Playgroud)
您可以想象prettyPrint
返回 a Function<A2, String>
(即F2 = A2
) 并且 A2 不是 A1 的超类。
所以我相信编译错误是有道理的。但我不会尝试根据规格来证明它,因为那会占用我一天的大部分时间!
归档时间: |
|
查看次数: |
3277 次 |
最近记录: |