Expression Language lambda type inference
Asked Answered
U

2

11

Normally I would do:

Function<Integer, Integer> a = b -> b * 2;
System.out.println(a.apply(3)); // prints 6

I was amazed to see that following EL expression works:

${a = b -> b * 2; a(3)}

The result of above EL expression is 6. How can compiler determine the type when declaring a in snippet 2 but requires type information in snippet 1?

Even this compiles and executes fine:

${(b -> b * 2)(3)}
Ursula answered 23/2, 2018 at 13:47 Comment(1)
Note that EL has its own Lambda processor and does not use Java's native one. Moreover, it was introduced far before Java 1.8 was introduced. You're essentially comparing apples with oranges.Matland
U
4

The EL evaluator / executor has no idea about the exact type of a in your EL expression. It just knows it should be a Number because of * operation

${a = b -> b * 2; a(3)}

Take a look at these results:

${a = b -> b * 2; a(3)}
6

${a = b -> b * 2; a('32')}
64

${a = b -> b * 2; a('32s')}
java.lang.NumberFormatException: For input string: "32s"

So only at runtime you will get an Exception, because Long.parse("32s") fails.

Look at this source code of ELArithmetic.java#211

Understandable answered 23/2, 2018 at 15:3 Comment(1)
Please note that EL is not "compiled" but "evaluated". In other words, EL does not at all use the Java compiler.Matland
H
-1

Fundamentally, the compiler is capable of inferring the types. If you rephrase snippet 1 a bit you can get something which compiles without explicitly declaring the type Integer:

public static  <V, R> R apply(Function<V, R> foo, V v) {
     return foo.apply(v);
}

System.out.println(apply(b -> b * 2, 3)); // prints 6

This comes close to the syntax: ${(b -> b * 2)(3)} The compiler just has specific difficulties with inferring the type of parameters of lambda expressions.

Horsey answered 23/2, 2018 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.