While coding, I spotted that replacing a lambda with a perfectly fine (IMO) method reference results in a compilation error using openJDK 17.
Investigation of the case led me to creating a minimal example of the code, that does not work in compilers that I found on my PC:
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
class ExampleTest {
public static void main(String[] args) {
SessionContext sessionContext = new SessionContext();
Entity foo = new Entity(null, "foo");
Optional<Long> id = sessionContext.get(session -> {
return Stream.of(foo)
.map(entity -> insert(entity, session))
.map(Entity::getId)
.findAny();
});
System.out.println(id);
}
static Entity insert(Entity entity, Session session) {
return session.persist(entity);
}
}
class Session {
Entity persist(Entity entity) {
entity.setId(42L);
return entity;
}
}
class SessionContext {
Session session = new Session();
<T> T get(Function<Session, T> query) {
return query.apply(session);
}
}
class Entity {
private Long id;
private String data;
Entity(Long id, String data) {
this.id = id;
this.data = data;
}
Long getId() {
return id;
}
void setId(Long id) {
this.id = id;
}
}
As far as I checked, the code compiles on openJDK 8. It does not compile on the following JVMs:
- openJDK 17;
- zulu16;
- zulu17;
- oracle 18.
Error displayed by the compilers:
ExampleTest.java:13: error: incompatible types: invalid method reference
.map(Entity::getId)
^
method getId in class Entity cannot be applied to given types
required: no arguments
found: Object
reason: actual and formal argument lists differ in length
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
There are other quirks too. If you follow the hint in the message above and use -Xdiags:verbose
... The compilation will automagically pass!
Please note that:
- The code example itself might not make much sense, it is just to illustrate the point in the most clear way.
- There can be a lot of refactorings done to the example code, but as far as I checked, they ultimately lead to not getting the compilation error.
Has anyone observed similar behavior? Does anyone recall if it is an official compilator error? Or maybe I am missing something in the code?
I expected this code to compile on all JVM as it looks OK.