Define a major Java version for all editions of Java

When defining a major version of Java in Java 8 and before it was customary to use the system property java.specification.version , java.specification.version 1. and analyze the second digit:

  • on Java 8 this will give "1.8" ~> "8" ~> 8
  • on Java 9, the same calls lead to a NumberFormatException because the system property is "9"

What is the future way to determine the core version of Java? The goal is to get an int , which can be if -ed or switch -ed over to decide which code to take the path (for example, in the library to activate the function).

+5
source share
4 answers

Java 9 introduces the Runtime.Version class, which I hope will be supported for some time. Matching it with the old approach, I got:

 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)); } } 

(I release this code under CC-0 : you can copy, modify, distribute, and do the work, even for commercial purposes, all without permission.)

It works on my machine (ha ha), but I'm not sure if this is the best solution, because I don't know if the new API or system property has any angular cases that I don't know from.

See also Steven 's answer on why reducing a version to one digit might not be a good idea in the first place.

+5
source

Obviously, nothing can be guaranteed in the future. We cannot predict the future with confidence (!)

However, for previous versions of Java and versions that comply with JEP 233 , the following will work:

  • If the version line starts with "1. [0-4]", use as is.
  • If the version line starts with "1. [5-8]", delete "1."
  • Otherwise, use the number before the first "."

But there is also the question of which version of the numbering you are using. For example, "Java 5" and "Java 1.5" mean the same thing. Which one you use depends on who you are trying to satisfy with your naming scheme.

A good (but not final) reference to what the "official" versions of Java versions mean:


Note that the original schema is interrupted for earlier versions of Java, such as "1.2.1" and "1.3.1", where the final number matters. And you do not want to start marking Java 1.0 as "Java 0". Finally, Java 1.0 and Java 1.1 are very different and should not be confused. (Java 1.0 has no nested / inner classes to start with.)


I would only do this with the goal of creating a "convenient manager." I would not reduce the version to one number for "decision making purposes." You may find that the differences between the younger versions are significant.

+5
source

Of course, it depends on the purpose of the operation. If you want to tell the user about this in a Java-compatible marketing, you will have to face the fact that the marketing itself has never used consistent labeling and can retroactively relate older versions.

If the check is intended only to ensure the presence of certain functions or bug fixes, it is enough to assign an ascending number for each version. You can then assign 0 to Java 1.0, which is significantly different from Java 1.1 (assign it 1 ) and get consistent numbering 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 version of a class file is that it is tied to a more formal definition, since it must fit into the two fields of the class file, so it cannot be subject to schema changes or retroactive overrides. In addition, there is no room for prose such as beta, final, or interpreted differently in these two versions. The only thing that protects the code above is the potential omission of the minor .0 , which was not used with Java 1.1, since the version of the main class file was increased for each version.

Of course, there is no guarantee that the number will increase again in each of the next releases, but this is not a problem for compatibility checks, since it will always have at least the previous version number, interpreted as “compatible with the previous release”. To start using the new features, you should still touch the source code. In this case, you can add the Runtime.version() operation for these future releases ...

But note that you get this for free when compiling with --release or --release , since the required minimum version is written to the class file anyway, and older versions of the JVM refuse to execute your code. If you want to optionally support the functions of a version later than the minimum version, you still have to access them dynamically, so in this case, you can just make a reflexive attempt to use this function, go to the backup code if it failed, and you don’t need to do additional verification of the version number. This is exactly what you are doing when trying to implement getMajorVersion() by making reflective Runtime.version().major() , without checking on the previous version for the presence of this function.

+3
source

As an alternative, and possibly to match only 1.5 and higher versions , the easiest way to use:

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

Source: https://habr.com/ru/post/1273314/


All Articles