【问题标题】:Anonymous classes field accessing on Java 1.8 compatibility with older versions匿名类字段访问 Java 1.8 与旧版本的兼容性
【发布时间】:2014-06-17 13:57:05
【问题描述】:

在 Java 1.8 上,您不必将字段定义为 final 即可从匿名类访问。

例如,在旧版本上:

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 上实现的唯一资源是这个(我没有使用任何 lambda、新类等),我的代码是否可以在具有旧 Java 的计算机上执行版本?如果不是,为什么?

【问题讨论】:

  • javac 根本不允许您将-source 1.8-target 1.7 结合使用。
  • 离题了,但我不想在没有明确声明我的最终参数或变量为 final 的情况下在 1.8 中编码。与 args 和 vars 在默认情况下实际上是不可变的其他语言不同,Java,这种语言,默认情况下总是使它们可变。所以现在,Java 1.8 正在做这种幕后魔术,有效地模糊了可变与不可变的界限。在代码可读性方面的想法很糟糕。

标签: java java-8 final anonymous-class


【解决方案1】:

当使用-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 处的字节减一一样简单。

如果您想创建与 Java 7 兼容的代码,那么棘手的部分是在使用 Java 8 编译器时约束自己不要使用其他 Java 8 功能……

【讨论】:

    【解决方案2】:

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

    如果用-target 1.7编译,不知道能不能有效使用final

    【讨论】:

      【解决方案3】:

      如果您在没有-target 1.7 -source 1.7 的情况下编译该代码,它将被编译为更新的字节码版本,而旧的 JVM 无法运行此类。

      如果您使用 -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 上运行这样的代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-06
        相关资源
        最近更新 更多