除非内联lambda表达式,否则Javac无法推断类型

时间:2017-11-17 22:45:42

标签: java lambda compiler-errors vavr

我使用Vavr获得以下Java代码片段。除非我内联参数,否则类型检查会失败。

为什么下面的代码不能被编译器接受?

import io.vavr.Function1;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.collection.List;
import io.vavr.Option;

import static io.vavr.collection.List.unfoldRight;

class A {}
class B {}
class Main {
    Function1<A, Option<Tuple2<B, A>>> f = (a) -> Option.of(Tuple.of(new B(), new A()));
    List<B> L0 = unfoldRight(new A(), f); // *
    List<B> L1 = unfoldRight(new A(), (a) -> Option.of(Tuple.of(new B(), new A()));

    Option<Tuple2<B, A>> g(A a) { return Option.of(Tuple.of(new B(), new A())); }
    List<B> L2 = unfoldRight(new A(), (a) -> g(a)); // **
}


// *  Compilation fails with: "Incompatible equality constraint: ? extends T and A"

// ** Compilation fails with: "Incompatible equality constraint: ? extends A and A"

这里是来自Vavr库的unfoldRight的方法签名:

static <T, U> List<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f)

这里是Github文档的链接:

https://github.com/vavr-io/vavr/blob/master/vavr/src/main/java/io/vavr/collection/List.java#L644-L671

1 个答案:

答案 0 :(得分:1)

关键是Option<Tuple<A, B>>不是Option<Tuple<? extends A, ? extends B>>的实例(尽管它是Option<? extends Tuple<? extends A, ? extends B>>)。

考虑List<Map<A, B>>List<Map<? extends A, ? extends B>>的情况(从类型安全角度来看与代码相同)。如果你能写:

List<Map<A, B>> list = new ArrayList<>();

// Compiler error! Pretend it's OK, though.
List<Map<? extends A, ? extends B>> list2 = list;

Map<SubclassOfA, SubclassOfB> map = new HashMap<>();
list2.add(map);

list.get(0).put(new A(), new B());

这是一个问题,因为map包含A,B类型的键/值对,而不是SubclassOfA,SubclassOfB。因此,如果您尝试从ClassCastException获取内容,则会获得map

// ClassCastException!
SubclassOfA soa = map.keySet().iterator().next();

Ideone demo

因此,编译器不允许这样做。

如果list2被声明为List<? extends Map<? extends A, ? extends B>>,则您无法致电list2.add(map),因此您无法解决同样的问题。因此,这项任务将被允许。

为您的类型添加通配符上限:

Function1<A, Option<Tuple2<? extends B, ? extends A>>> f = ...
Option<Tuple2<? extends B, ? extends A>> g(A a) { ... }