Lambda as a combination of methods from the Predicate interface doesn't compile if it is written as one statement

非 Y 不嫁゛ 提交于 2019-12-01 02:04:54

问题


What is the difference between both these ways of lambda creation? Why doesn't the first one compile?

Predicate<Integer> predicate = Predicate.isEqual(0).or(Predicate.isEqual(1));

Gives: error: incompatible types: Predicate<Object> cannot be converted to Predicate<Integer> = Predicate.isEqual(0).or(Predicate.isEqual(1));

Predicate<Integer> pred21 = Predicate.isEqual(0);
Predicate<Integer> pred22 = pred21.or(Predicate.isEqual(1));

This one works.


回答1:


Adding <Integer> before the isEqual method call should help :

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0).or(Predicate.isEqual(1));

The reason behind such compiler behavior:

  • isEqual is a static generic method which returns Predicate<T> (no matter what actual type of its input parameter is), so it returns Predicate<Object> when calling the method without specifying returning type explicitly.
  • or is also a static generic method, but it returns a predicate parametrized by the same type, as its input parameter (which is Predicate<Object>).



回答2:


The problem is related to the way which the inference works in Java : it depends on the target.

Here :

Predicate<Integer> predicate = Predicate.isEqual(0)
                                        .or(Predicate.isEqual(1));

The type returned by or(Predicate.isEqual(1)) depends on the type returned by Predicate.isEqual(0) (the nearest target) but this invocation doesn't specify any other type as return.
So Object is returned by or(Predicate.isEqual(1)) as the method isEqual() defines T as return type without any wildcard :

static <T> Predicate<T> isEqual(Object targetRef) {

To solve your issue you indeed need to specify the return type of the first invocation in order to allow the chained invocation to infer the correct type : Integer.

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0)
                                        .or(Predicate.isEqual(1));



回答3:


This happens because

Predicate.isEqual(0)

has this signature:

static <T> Predicate<T> isEqual(Object targetRef)

It infer Predicate<Object> if you don't type it.

To type it you can type the return type

Predicate<Integer> pred21 = Predicate.isEqual(0);

Or type the call like

Preicate.<Integer>isEqual



回答4:


Look at the signature:

 static <T> Predicate<T>    isEqual​(Object targetRef)

In the first example, the compiler cannot guess the generic type parameter, so it returns a Predicate<Object>.

The correct way to type it in one line would be to specify the type parameter like

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0).or(Predicate.isEqual(1));


来源:https://stackoverflow.com/questions/50152693/lambda-as-a-combination-of-methods-from-the-predicate-interface-doesnt-compile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!