6

So i'm a little confused about a change in Java 8 - List.sort - bear with me as the confusion will become apparent.

I have Java 8 JDK installed and running Eclipse with the Project in question set to compile in 1.6 (Windows environment).

Throughout my code I've been doing (Example extends BaseExample):

public static final Comparator<BaseExample> sortByLevel_DESC = new Comparator<NavItemBase>() {...};

List<Example> examples = new ArrayList<Example>();

examples.sort(sortByLevel_DESC);

Despite compiling to 1.6, this worked, and has always worked for me (remember i have Java 8 installed).

However...

Since applying this code to a clients machine - with Java 7 (JRE not JDK) installed (Linux Environment), the exception "java.util.List.sort() NoSuchMethodException" is thrown.

Changing the code from: examples.sort(sortByLevel_DESC); to: Collections.sort(examples, sortByLevel_DESC); resolves the issue.

This leads me to the obvious conclusion that its due to the Java 8 specific code, and due to Java 8 not being installed, it falls over.

But i'm left wondering...

Why eclipse does not complain about Java 8 code when not compiled to Java 8 in the exact same way it will complain if you try to use Lambda expressions while not compiled to Java 8:

examples.stream().filter(e -> e.active()).collect(Collectors.toList());

(e -> e.active()) being the problem:

1.8 source

I would have thought if the method was java 8 only, and i was compiled to 6, then only java 6 code can be executed - I have actually relied on this "project specific setting" to to ensure i don't write any code that is not compatible with the lower version that clients often have, like when i tried the lambda expression.

Perhaps this is actually a problem with Eclipse and not Java? Or perhaps this is NOT the same as lambda expressions at all (in the way it should show an error)?

Steve
  • 178
  • 2
  • 12
  • 1
    How did you set up the Java 6 compatibility mode? Using the compliance level in Eclipse? – Tom May 30 '17 at 15:06
  • 2
    "Perhaps this is actually a problem with Eclipse and not Java". It's absolutely a problem with Eclipse. IDEA has two settings: language level and JDK. JDK contains class definitions e.g. methods you can use (like `List.sort`. Language level defines which syntax constructs you can use. I don't know how Eclipse deals with this. – Michael May 30 '17 at 15:10
  • @JornVernee I don't think that the IDE compiles that code in a style matching the language level settings (or "compliance level" in Eclipse). It just sets the file format, like you said and checks that you don't use stuff not working in that version, like methods with an `@since` annotation > the current version. – Tom May 30 '17 at 15:13
  • @Tom I just remembered that `invokedynamic` was already in Java 7 as well. But `sort` _does_ have a `@since 1.8` annotation. – Jorn Vernee May 30 '17 at 15:21
  • @JornVernee That's why it should fail on both Java 6 and Java 7. I guess OP didn't set up Java 6 compatibility correctly and that's why he didn't had any issues, yet. (And that's why I asked him about that :D) – Tom May 30 '17 at 15:24

2 Answers2

3

When it comes to working out what methods a class or interface has Eclipse just uses the runtime jars in whatever JRE (or JDK) you have specified for the project in the Java Build Path.

So to check that your code compiles with Java 6 you need to tell Eclipse about a Java 6 JRE in the Preferences in 'Java > Installed JREs'. You then use that JRE for the project (in the 'Library' tab of 'Java Build Path' in the project Properties).

Note that changing the execution environment to Java 1.6 is not enough unless you have an 'perfect match' JRE/JDK installed.

greg-449
  • 109,219
  • 232
  • 102
  • 145
  • This was it exactly, I've always changed the compiler but I don't ever remember changing the build path system lib - so this is useful information, thanks to all who provided assistance. – Steve May 30 '17 at 16:06
  • Probably shouldn't have marked as the correct answerso hastily - yes its true my lib wasn't set to use 1.6, however after doing so, Eclipse still "allows" the problem code (no warning or error is displayed). – Steve May 31 '17 at 11:53
2

The issue is definitely with the settings in eclipse, please follow the steps mentioned below to avoid the problem you are facing.

From the menu bar: Project -> Properties -> Java Compiler

Enable project specific settings (checked) Uncheck "use Compliance from execution environment '.... Select the desired "compiler compliance level"

That will allow you to compile "1.6" code using a "1.8" JDK.

If you want to acutally use a 1.6 JDK to produce "1.6" compliant code, then install a suitable 1.6 JDK and tell eclipse where it is installed via:

Window -> preferences -> Installed JREs

And then go back to your project

Project -> properties -> Java Build Path -> libraries

remove the 1.8 system libaries, and: add library... -> JRE System LIbrary -> Alternate JRE -> The JRE you want.

Verify that the correct JRE is on the project's build path, save everything, and enjoy!

Reference : how do I get eclipse to use a different compiler version for Java?

Sadiq Ali
  • 1,272
  • 2
  • 15
  • 22
  • 1
    I'm changing the correct answer to this one, as you have to acctualy have a 1.6 JDK (or jre) - previously i was changing the project's library to use an execution environment 1.6 (e.g. SDK 1.6 (jdk 1.8)) - since downloading Java 6 and adding the JDK as an "Installed JRE" (as Sadiq suggests) is the way to go. Doing this allowed me to change the project specific lib and the error appears as expected. – Steve May 31 '17 at 12:32