Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics and lambdas - different behavior in javac and Eclipse compiler

Note: I found multiple questions pointing out differences between javac and the Eclipse compiler, but as far as I could see all of them discuss other issues.

Suppose we have this method:

public static <T, U> void foo(Supplier<T> a, Function<T, U> b, Consumer<U> c)
{
    c.accept(b.apply(a.get()));
}

I found different behavior between javac and the Eclipse Java compiler when compiling calls to this method and I'm not sure which of the two is right.


A simple use of this method could be:

// variant 1
foo(
    () -> Optional.of("foo"),
    value -> value.get(),
    value -> System.out.println(value));

The compiler should be able to bind T to Optional<String> using the first argument and U to String using the second. So this call should be valid (in my opinion).

This compiles fine using javac but fails to compile using Eclipse:

Type mismatch: cannot convert from void to <unknown>

Adding a type argument to the first argument (() -> Optional.<String> of("foo")) makes it compile in Eclipse too.

Question: From a specification point of view, is Eclipse correct in rejecting this call (and why (not))?


Now suppose we want to throw a custom (runtime) exception, if the Optional is empty:

// variant 2
foo(
    () -> Optional.of("foo"),
    value -> value.orElseThrow(() -> new RuntimeException()),
    value -> System.out.println(value));

This is rejected by both, javac and the Eclipse compiler, but with different error messages:

  • javac: "unreported exception X; must be caught or declared to be thrown"
  • Eclipse compiler: "Type mismatch: cannot convert from void to <unknown>"

When I add the type argument to the first argument as above, Eclipse succeeds in compiling while javac still fails. When I add <RuntimeException> as type argument to the second argument, it's the other way around, Eclipse fails and javac succeeds.

Question: Again, are the compilers right in rejecting this call and why?


In my opinion both variants should compile fine without additional hints by using type arguments. If so I'll fill one bug report for javac (regarding the "unreported exception") and one for the Eclipse compiler (regarding the "type mismatch"). But first I want to be sure the specification shares my point of view.

Versions used:

  • javac: 1.8.0_66
  • Eclipse JDT: 3.11.1.v20151118-1100

EDIT:

I filled bug 482781 for the issue in Eclipse.

The issue with javac is already reported as JDK-8056983, see Tunakis answer.

like image 537
siegi Avatar asked Nov 21 '15 19:11

siegi


People also ask

Is Eclipse a compiler?

Eclipse does have it's own compiler, it does not use the JDK compiler (javac). However, Eclipse's compiler produces standard bytecode that complies with the Java Language Specification (JLS) and JVM Specification, so the compiled code it produces will work on any compliant JVM.

What is ECJ compiler?

ECJ, the Eclipse Compiler for Java, is an open source incremental compiler used by the Eclipse JDT. It is an option for Liferay builds and is in many cases faster than Javac or Jikes. The jar for ECJ is included in Liferay release 4.4.


1 Answers

Yes, you're right in every aspect. I honestly wouldn't be able to link to specific lines of the JLS about this: type inference is a whole chapter.

Disclaimer: I tested using Eclipse Mars 4.5.1 and JDK 1.8.0_60.


Variant 1 should compile and Eclipse has a bug here. I couldn't find anything related to this in their Bugzilla so you could go ahead and file it. You can assure yourself that it should compile if you reduce your example to this:

public static <T> void foo(Supplier<T> a) {
    a.get();
}

foo(() -> Optional.of("foo"));

This compiles fine both with Eclipse and javac. Adding parameters does (should) not change the type inferred for T during compilation.


Variant 2 does not compile for javac and this is indeed a bug, as reported in JDK-8056983. The compiler should be able to infer that X is RuntimeException. As to why Eclipse is still not able to compile this, again, I couldn't find anything in their Bugzilla so feel free to report this!

like image 184
Tunaki Avatar answered Nov 14 '22 22:11

Tunaki