2017-11-17 47 views
0

我有以下的使用Vavr的Java代码片段。类型检查失败,除非我内联一个参数。Javac不能推断类型,除非lambda表达式被内联

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

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

的关键是, 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的。因此,如果您试图从map获取东西,则会得到ClassCastException

// 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) { ... } 
+0

哦,对了,这是'''不兼容的不等式约束:(?延伸A,A)'''不'''不兼容的不等式约束:( ?扩展A,?扩展A)'''。非常感谢! – Zaaier