确定所有Java版本中的主要Java版本

时间:2017-11-13 09:52:55

标签: java java-9

在确定Java 8上的主要Java版本时,在通常使用系统属性java.specification.version之前,删除1.并解析第二个数字:

  • 在Java 8上,这将产生"1.8"〜> "8"〜> 8
  • 在Java 9上,相同的调用导致NumberFormatException,因为系统属性为"9"

确定主要Java版本的前瞻性方法是什么?我们的目标是获得一个int if - 或switch - 来决定采用哪种代码路径(例如在库中激活某项功能)。

4 个答案:

答案 0 :(得分:6)

Java 9引入了Runtime.Version类,希望在未来一段时间内得到支持。将它与我得到的旧方法配对:

public static int getMajorVersion() {
    try {
        // use Java 9+ version API via reflection, so it can be compiled for older versions
        Method runtime_version = Runtime.class.getMethod("version");
        Object version = runtime_version.invoke(null);
        Method version_major = runtime_version.getReturnType().getMethod("major");
        return (int) version_major.invoke(version);
    // do not catch `ReflectiveOperationException` because it does not exist in Java <7
    } catch (Exception ex) {
        // before Java 9 system property 'java.specification.version'
        // is of the form '1.major', so return the int after '1.'
        String versionString = System.getProperty("java.specification.version");
        return Integer.parseInt(versionString.substring(2));
    }
}

(我在CC-0下发布此代码:您可以复制,修改,分发和执行工作,即使是出于商业目的,也可以不经许可。)

它适用于我的机器(哈哈),但我不确定这是否是最佳解决方案,因为我不知道新API或系统属性是否有任何我不知道的极端情况的。

另请参阅Stephen's answer了解为什么首先将版本缩减为单个数字可能不是一个好主意。

答案 1 :(得分:5)

显然,没有任何东西可以保证是面向未来的。我们无法确定地预测未来(!)

但是,以下版本适用于以前版本的Java和符合JEP 233的版本:

  1. 如果版本字符串以“1. [0-4]”开头,则按原样使用。
  2. 如果版本字符串以“1. [5-8]”开头,则删除“1。”
  3. 否则,请使用第一个“。”之前的数字。
  4. 但是还有你使用的编号版本的问题。例如,“Java 5”和“Java 1.5”意思相同。您使用哪种方法取决于您尝试使用命名方案满足的人。

    关于“官方”Java版本名称的一个好的(但不是明确的)参考:

    请注意,您的原始方案会破坏早期Java版本,例如“1.2.1”和“1.3.1”,其中最终数字很重要。并且您不希望开始将Java 1.0标记为“Java 0”。最后,Java 1.0和Java 1.1非常不同,不应混淆。 (Java 1.0没有嵌套/内部类,一开始。)

    我只会 这样做是为了制作一个“经理友好”的名字。为了“决策目的”,我不会将版本缩减为单个数字。您可能会发现次要版本之间的差异很大。

答案 2 :(得分:3)

当然,这取决于手术的目标。如果您想以Java营销兼容的方式向用户报告,您必须面对这样一个事实:营销本身从未使用过一致的标签,并且可以追溯性地重新标记旧版本。

如果检查仅用于确保某些功能或错误修复的存在,只需为每个版本分配一个升序编号就足够了。然后,您可以将0分配给Java 1.0,这与Java 1.1(为其分配1)显着不同,并使用

获得最多9个的一致编号
public static int getMajorVersion() {
    String version = System.getProperty("java.class.version");
    int p = version.indexOf('.');
    if(p>0) version = version.substring(0, p);
    return Integer.parseInt(version)-44;
}

类文件版本的好处在于它必须绑定到更正式的定义,因为它必须适合类文件的两个字段,因此它不能进行方案更改或追溯重新定义。此外,在这两个版本号中,没有像“beta”,“final”或“请解释不同”等散文的空间。上面的代码唯一可以防止的是,自Java 1.1以来,.0次要编号可能遗漏,因为主要的类文件版本已经为每个版本增加了。

当然,没有保证在下一个版本中每个版本都会再次增加该数字,但是,这不是兼容性检查的问题,因为它始终具有至少上一版本的编号,被解释为“与先前版本兼容”。要开始使用较新的功能,您无论如何都必须触摸源代码。在这种情况下,您可以为这些将来的版本添加基于Runtime.version()的操作......

但请注意,在使用-target--release进行编译时,您可以免费获得此内容,因为无论如何都会将所需的最低版本写入类文件,而较旧的JVM版本将拒绝执行您的代码。当您希望选择支持比最低版本更新的版本的功能时,您必须动态访问它们,因此在这种情况下,您可以只是反复尝试使用该功能,如果失败则转到后备代码,并且不需要进行额外的版本号检查。这正是您在尝试实施getMajorVersion()执行反思Runtime.version().major()时所做的工作,而没有基于先前版本的检查是否存在该功能。

答案 3 :(得分:1)

或者可能仅仅遵守1.5 and above versions,更简单的方法仍然可以使用:

private static int getMajorVersion() {
    String systemVersionProperty = System.getProperty("java.specification.version");
    return systemVersionProperty.contains(".") ? Integer.parseInt(systemVersionProperty.substring(2)) :
            Integer.parseInt(systemVersionProperty);
}