2014-06-17 34 views
5

在Java 1.8上,您不必将字段定义为final,以便从匿名类进行访问。匿名类字段访问Java 1.8与旧版本的兼容性

例如,在旧版本:

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

但是,现在,关于Java 1.8,bar并不需要是最后:

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

所以,如果我编译我的项目,在Java 1.8上实现的惟一资源是我使用的(我没有使用任何lambdas,新类等),我的代码是否可以在具有较旧Java版本的计算机上执行?如果不是,为什么?

+3

你可能错过了这个[之间的差异最终和有效决赛]( http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final) –

+2

'javac'根本不允许你将'-source 1.8'和'-target 1.7'结合起来。 – Holger

+0

走出正切,但我不想在1.8中编码,而没有明确声明我的最终参数或变量为* final *。与默认情况下args和vars实际上不可变的其他语言不同,Java(语言)默认情况下始终使它们可变。所以现在,Java 1.8正在做这种幕后魔法,它有效地模糊了可变和不可变的界限。当涉及代码可读性时,这个想法太糟糕了。 –

回答

6

-target 1.8编译,javac运行这样的代码将发出版本号为52.0的类文件,这是以前的JVM不支持的。所以即使这是唯一的区别,它也会阻止您执行使用-target 1.8编译的文件。

javac不支持同时指定-source 1.8-target 1.7。它会产生错误信息source release 1.8 requires target release 1.8

但的确,如果使用有效的最终变量是唯一使用的Java 8功能,除了版本号之外,没有字节码差异。如果您编译的代码定位为1.8并将类文件的版本号减少到51.0,则它们将在Java 7上运行。这与将索引7中的字节减少1一样简单。

棘手的部分是约束自己使用Java 8编译器时,如果你想创建Java 7兼容的代码不使用其他Java 8功能...

1

我认为Java 8将类文件主版本更改为与Java 7不同,因此较旧的JVM可能无法加载较新的类。

如果用-target 1.7编译,我不知道如果你编译代码,无需-target 1.7 -source 1.7它会被编译成字节码较新版本的老JVM的不能跑这样你可以使用有效最终

0

类。

如果您编译例如与-target 1.7 -source 1.7选项 - 并发症会失败 有消息

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

所以,答案是否定的,你不能在旧JVM的