所以,我制作了这个相对的简单代码,我和IntelliJ IDEA都没有看到它有什么问题,但是javac在标记的行上徘徊,抱怨它无法推断出类型:< / p>
import java.util.List;
import java.util.stream.Collectors;
public class GenericsBreakJavac8 {
public interface Edge<N> {
N getNode();
}
@FunctionalInterface
public interface EdgeCreator<N, E extends Edge<N>> {
E createEdge(N node);
}
public static <N> List<Edge<N>> createEdges(List<N> nodes) {
return createEdges(nodes, DefaultEdge::new); //the deadly line
}
//THE NEWLY ADDED LINE (see the edit note)
public static <N> List<Edge<N>> createEdges2(List<N> nodes) {
return createEdges(nodes, n -> new DefaultEdge<N>(n));
}
public static <N, E extends Edge<N>> List<E> createEdges(List<N> nodes, EdgeCreator<N, E> edgeCreator) {
return nodes.stream().map(edgeCreator::createEdge).collect(Collectors.toList());
}
public static class DefaultEdge<N> implements Edge<N> {
private final N node;
public DefaultEdge(N node) {
this.node = node;
}
@Override
public N getNode() {
return node;
}
}
}
使用显式类型将有问题的行拆分为2会有所帮助,但类型签名比lambda长,完全违背了编写lambda的目的......
修改 如果我使用实际的lambda而不是方法引用,我会再次遇到问题。请参阅上面新添加的方法。
答案 0 :(得分:8)
javac
并不认为DefaultEdge
是原始类型。
return createEdges(nodes, DefaultEdge<N>::new);
将按预期工作。
答案 1 :(得分:4)
除了Jeffrey’s answer之外,请注意您的EdgeCreator
界面在功能上与Function
没有区别,createEdges
实际上并不需要有问题的类型约束。因此,一个解决方案是让EdgeCreator
扩展Function
以简化createEdges
。
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class GenericsBreakJavac8 {
public interface Edge<N> {
N getNode();
}
@FunctionalInterface
public interface EdgeCreator<N, E extends Edge<N>> extends Function<N,E> {
E createEdge(N node);
@Override public default E apply(N t) { return createEdge(t); }
}
public static <N> List<Edge<N>> createEdges(List<N> nodes) {
return createEdges(nodes, DefaultEdge::new);
}
public static <N> List<Edge<N>> createEdges2(List<N> nodes) {
return createEdges(nodes, n -> new DefaultEdge<>(n));
}
public static <T,R> List<R> createEdges(List<T> nodes, Function<T,R> edgeCreator) {
return nodes.stream().map(edgeCreator).collect(Collectors.toList());
}
public static class DefaultEdge<N> implements Edge<N> {
private final N node;
public DefaultEdge(N node) {
this.node = node;
}
@Override
public N getNode() {
return node;
}
}
}
您也可以删除EdgeCreator
接口,并在需要强制执行约束的地方使用Function<N, E extends Edge<N>>
,但在此代码中,没有这样的地方。当有人试图使用createEdges(List,Function)
时,约束仍然会被强制执行。其结果,在上下文中,需要List<Edge<SpecificNodeType>>
。
对太多代码位置进行类型约束只会让您的源代码膨胀而无益。
顺便说一下,在你当前的代码中,你甚至不需要DefaultEdge
类;你可以将整个代码简化为
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class GenericsBreakJavac8 {
public interface Edge<N> {
N getNode();
}
public static <N> List<Edge<N>> createEdges(List<N> nodes) {
return createEdges(nodes, n -> () -> n);
}
public static <T,R> List<R> createEdges(List<T> nodes, Function<T,R> edgeCreator) {
return nodes.stream().map(edgeCreator).collect(Collectors.toList());
}
}