Why does Eclipse allow me to compile some Java 7 language features into Java 6 class files?

I found that in Eclipse (using the Eclipse compiler) I can use some Java 7 language functions, but still create Java 6 class files. In the following figure, you can see two Java 7 language functions that have been successfully compiled as a Java 6 class file However, other Java 7 features that are commented out do not compile.

My guess is that Eclipse determines which Java 7 features are compatible with the Java 6 JVM and which are not. For example, the generic JComboBox type is just compilation (not runtime), so I can imagine how it will be compatible. The String function of the switch, although I would have thought it could make a difference in byte code and rely on the new features of the JVM, but I could be wrong ...

My questions:

  • Is Eclipse smart enough to know which Java 7 language functions can be compiled into Java 6 class files and which ones cannot?

  • The example below is clearly not compatible with source code 1.6, so why setting the "Source Compatibility" to 1.6 does not cause an error?

  • This "trick" allows me to use at least some features of the Java 7 language and still create Java 6 class files. Using javac with source code 1.7 and target 1.6 will fail, so why does it work? Does the Ecilpse compiler have a function that is not in javac?

enter image description here

For comparison, here is the result when I switch to the Java 6 compiler, as expected.

enter image description here

+5
source share
4 answers

I think two things happen:

  • I suspect that the first line (with a common JComboBox ) works because Java 1.7 rt.jar is linked instead of Java 1.6 rt.jar (I have a project that is configured using JavaSE-1.6, in which case this first line will not compile even with your first combination of settings). But this is a class library problem, not a language version problem. (You can get a lot of problems even with javac if you compile your Java application against a newer rt.jar than when you run it).

  • The second line probably represents an error in the Eclipse compiler. Although most of the functions of the Java 7 language can be implemented exclusively in the compiler (which Android has been doing since the end of 2013), the execution is obviously not compatible with the source code with Java 6.

So, in a word, you have found at least one error in the (possibly) unusual configuration of Eclipse. Be careful not to rely on him.

+1
source

I do not know why Eclipse resolves this or is it just a mistake. 1.7 javac will tell you what

 error: strings in switch are not supported in -source 1.6 

I also don't know why JComboBox works,

 System.out.println(new JComboBox<String>() {}.getClass().getGenericSuperclass()); > javax.swing.JComboBox<java.lang.String> 

has general information at run time, which should not be. Allow the use of generics for classes that are not common if the IMO is rejected as incompatible. However, I did not work on the JVM6 code. Perhaps this is even a glitch.

But at least switch not technically a problem. http://www.benf.org/other/cfr/java7switchonstring.html shows that this is just a compiler trick that does not require a new language function, API or bytecode.

A simplified example:

 int java7(String string) { switch (string) { case "BB": return 12; case "FRED": return 13; } return 0; } 

becomes significant

 int java6(String string) { switch (string.hashCode()) { case 2112: if (string.equals("BB")) return 12; break; case 2166379: if (string.equals("FRED")) return 13; break; } return 0; } 

This is based on the fact that the result of String#hashCode() is specified and should not be changed. The compiler will save you some time to write code faster that does not have a legal code.

The same applies to the diamond operator: for example. new ArrayList<>() can simply be resolved by the compiler.

The android tools that allow you to use the same compatibility with seven 7 allow you to use it. However, the difference is that they use .class files oriented to Java 7. Android needs to convert the .class files to its internal format anyway, so their .class to .dex compiler can use any input to generate instructions that understood Android runtime.

try-with-resource, for example, will not work, since it requires, among others, the AutoCloseable c interface did not exist in Java 6.

And special features like Lambda expressions also require new types of bytecode.

+1
source

My guess is that you are right in why ECJ will compile something and not others when it is installed in Java 6. Generators just compile with the same things as casts, so it is possible that this works if for the purpose set to java 6?

See What is the difference between javac and the Eclipse compiler? for other differences between javac and ECJ.

0
source

This may be due to the JRE System Library configured on your project build path that does not match the selected level of compliance. Usually you almost always want to select the option "Use compliance from the runtime" in the project compiler settings. Check your Build Path project and see if you have specified the JRE System Library as the runtime.

0
source

Source: https://habr.com/ru/post/1205877/


All Articles