I've been working with the new Eclipse Neon and some of my code started to give me errors straight away.
This was strange to me at first, but then I found here that the Neon ECJ(Eclipse Java Compiler) adopts the attitude of the JDK 9 early release compiler.
I do not encounter the same issue that is in that link, but rather another that I will explain here.
Issue with Lambda Expression declarations as fields
Here is a test class that gives me a compilation error in Eclipse Neon, the JDK 9 compiler, and the JDK 8 compiler (Not previous versions of Eclipse though).
public class Weird
{
private final Function<String, String> addSuffix =
text -> String.format( "%s.%s", text, this.suffix );
private final String suffix;
public Weird( String suffix )
{
this.suffix = suffix;
}
}
Given the code above, the errors at line 4 for suffix
are:
╔══════════╦═══════════════════════════════════════════════╗
║ Compiler ║ Error ║
╠══════════╬═══════════════════════════════════════════════╣
║ ECJ ║ Cannot reference a field before it is defined ║
║ JDK 9 ║ error: illegal forward reference ║
╚══════════╩═══════════════════════════════════════════════╝
Now see what happens with the same class if I move the suffix
field declaration before the the addSuffix
declaration.
public class Weird
{
private final String suffix;
private final Function<String, String> addSuffix =
text -> String.format( "%s.%s", text, this.suffix );
public Weird( String suffix )
{
this.suffix = suffix;
}
}
Given the code above, the errors at line 6 for suffix
are:
╔══════════╦════════════════════════════════════════════════════════════╗
║ Compiler ║ Error ║
╠══════════╬════════════════════════════════════════════════════════════╣
║ ECJ ║ The blank final field suffix may not have been initialized ║
║ JDK 9 ║ error: variable suffix might not have been initialized ║
╚══════════╩════════════════════════════════════════════════════════════╝
Should Java 9 behave this way?
This worked perfectly fine in JDK 8; seems like a strange thing to suddenly enforce. Especially considering that there are already compile-time checks in place to ensure final fields are instantiated correctly.
Therefore, by the time the function addSuffix
is ever accessed, there would need to be a value in place for suffix
(null
or otherwise is another story).
I'll also note that I've tried the following code, which compiles fine with JDK9 and ECJ:
public class Weird
{
private final String suffix;
private final Function<String, String> addSuffix =
new Function<String, String>()
{
@Override
public String apply( String text )
{
return String.format( "%s.%s", text, suffix );
}
};
public Weird( String suffix )
{
this.suffix = suffix;
}
}
It appears that in JDK 9, there is a big difference between anonymous class declarations and Lambda expressions. So in this case where we get a compiler error, at least the ECJ is accurately in mimicking the JDK 9 compiler.
Issue with Stream & Generics
This one really surprised me, because I cannot think of why the compiler would interpret this any differently than what the Generic in the code indicates:
public class Weird
{
public void makePDFnames( String [] names )
{
final List<String> messages = Arrays.asList( "nice_beard", "bro_ski" );
final List<String> components = messages.stream()
.flatMap( s -> Stream.of( s.split( "_" ) ) )
.collect( Collectors.toList() );
}
}
This code gives these errors:
╔══════════╦═══════════════════════════════════════════════════════════════════════╗
║ Compiler ║ Error ║
╠══════════╬═══════════════════════════════════════════════════════════════════════╣
║ ECJ ║ Type mismatch: cannot convert from List<Serializable> to List<String> ║
║ JDK 9 ║ NO ERROR. Compiles fine! ║
╚══════════╩═══════════════════════════════════════════════════════════════════════╝
In light of this information, it appears in this case, the ECJ is at fault for not properly mimicking the JDK 9 and is just an Eclipse bug.
this
keyword. I'll edit the question now. However, in the anonymous class declaration, you cannot usethis
because then that would of course refer to the instance you are creating. – Mausoleumsuffix
should be initialized – Vivienvivienefinal
modifier fromsuffix
field – Vivienviviene