在确定Java 8上的主要Java版本时,在通常使用系统属性java.specification.version
之前,删除1.
并解析第二个数字:
"1.8"
〜> "8"
〜> 8
NumberFormatException
,因为系统属性为"9"
确定主要Java版本的前瞻性方法是什么?我们的目标是获得一个int
if
- 或switch
- 来决定采用哪种代码路径(例如在库中激活某项功能)。
答案 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的版本:
但是还有你使用的编号版本的问题。例如,“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
)显着不同,并使用
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);
}