Of course, it depends on the goal of the operation. If you want to report it to the user in a Java marketing compatible way, you have to face the fact that the marketing itself never used a consistent labeling and may retroactively relabel old versions.
If the check is only intended to ensure the presence of certain features or bug fixes, just assigning an ascending number to every release would be sufficient. Then, you may assign 0 to Java 1.0, which is significantly different from Java 1.1 (assign 1 to it) and get a consistent numbering up to nine using
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;
}
The good thing about the class file version is that it is bound to a more formal definition, as it has to fit into the two fields of a class file, so it can’t be subject to scheme changes nor retroactive redefinition. Also, there is no room for prose like “beta”, “final”, or “please interpret differently” in these two version numbers. The only thing, the code above protects against, is the potential omission of the .0 minor number which has not been used since Java 1.1, as the major class file version has been incremented for every release.
Of course, there is no guaranty that the number will be incremented again in each of the next releases, however, this is not an issue for compatibility checks, as it will always have at least the number of the previous release, being interpreted as “compatible with the previous release”. To start using newer features, you have to touch the source code anyway. In that case, you may add the Runtime.version() based operation for these future releases…
But note that you get this for free when compiling with -target or --release, as the required minimum version is written into the class file anyway and older JVM versions will refuse to execute your code. When you want to optionally support features of a version newer than the minimum release, you have to access them dynamically anyway, so in this case, you can simply make a reflective attempt to use the feature, going to the fallback code if failed, and don’t need to do an additional version number check. That’s exactly what you are doing when trying to implement getMajorVersion() doing a reflective Runtime.version().major(), without a preceding version based check for the presence of that feature.