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

廉价感情. 提交于 2019-12-01 05:39:46

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>).

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));

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

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