5

On Java 1.8, you don't have to define a field as final to it be acessed from anonymous classes.

For example, on older versions:

public void foo(final int bar) {
  new Runnable() {
    public void run() {
      System.out.println(bar);
    }
  };
}

But, now, on Java 1.8, bar does not need to be final:

public void foo(int bar) {
  new Runnable() {
    public void run() {
      System.out.println(bar);
    }
  };
}

So, if I compile my project, and the only resource implemented on Java 1.8 I'm using is this (I'm not using any lambdas, new classes, etc), will my code be executable on computers with older Java versions? If not, why?

  • 3
    You might missed this [Difference between final and effectively final](http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final) – Suresh Atta Jun 17 '14 at 13:58
  • 2
    `javac` simply doesn’t allow you to combine `-source 1.8` with `-target 1.7`. – Holger Jun 17 '14 at 16:29
  • Going off the tangent, but I wouldn't like to code in 1.8 without explicitly declaring my final args or variables as *final*. Unlike other languages where args and vars are effectively immutable by default, Java, the language, has always made them mutable, by default. So now, Java 1.8 is doing this magic-behind-the-scenes that effectively blurs the line of what is mutable and what is not. Terrible idea when it comes to code readibility. – luis.espinal Jul 04 '14 at 00:03

3 Answers3

6

When compiling with -target 1.8, javac will emit class files with a version number of 52.0 which is not supported by previous JVMs. So even if that’s the only difference it prevents you from executing files compiled with -target 1.8.

And javac doesn’t support specifying -source 1.8 and -target 1.7 at the same time. It will produce the error message source release 1.8 requires target release 1.8.

But indeed, if using effectively final variables is the only Java 8 feature you are using, there is no byte code difference besides the version number. If you compile such code targeting 1.8 and patch the class files reducing the version number to 51.0 they will run on Java 7. It’s as simple as reducing the byte at index 7 by one.

The tricky part is to discipline yourself to not using other Java 8 features when using a Java 8 compiler if you want to create Java 7 compatible code…

Holger
  • 285,553
  • 42
  • 434
  • 765
1

I think Java 8 changed the class file major version to be different than Java 7 so an older JVM probably won't be able to load the newer classes.

If you compile with a -target 1.7, I don't know if you can use effectively final

dkatzel
  • 31,188
  • 3
  • 63
  • 67
0

If you compile that code without -target 1.7 -source 1.7 it will be compiled to newer bytecode version and old JVM's could not run such classes.

If you compile your example with -target 1.7 -source 1.7 options - complication will fail with message

error: local variable bar is accessed from within inner class; needs to be declared final
                                System.out.println(bar);
                                                   ^

so, answer is NO, you cannot run such code on older JVM's