--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java Thu Apr 20 22:46:22 2017 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java Fri Apr 21 19:13:47 2017 +0100
@@ -930,10 +930,9 @@
}
/**
- * Returns the version of the Java Runtime Environment as a {@link
- * Runtime.Version}.
+ * Returns the version of the Java Runtime Environment as a {@link Version}.
*
- * @return the {@link Runtime.Version} of the Java Runtime Environment
+ * @return the {@link Version} of the Java Runtime Environment
*
* @since 9
*/
@@ -948,7 +947,7 @@
/**
* A representation of a version string for an implementation of the
- * Java SE Platform. A version string contains a version number
+ * Java SE Platform. A version string consists of a version number
* optionally followed by pre-release and build information.
*
* <h2><a name="verNum">Version numbers</a></h2>
@@ -960,7 +959,7 @@
* </p>
*
* <blockquote><pre>
- * ^[1-9][0-9]*(((\.0)*\.[1-9][0-9]*)*)*$
+ * [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
* </pre></blockquote>
*
* <p> The sequence may be of arbitrary length but the first three
@@ -1026,10 +1025,13 @@
*
* <p> A <em>version string</em>, {@code $VSTR}, consists of a version
* number {@code $VNUM}, as described above, optionally followed by
- * pre-release and build information, in the format </p>
+ * pre-release and build information, in one of the following formats:
+ * </p>
*
* <blockquote><pre>
- * $VNUM(-$PRE)?(\+($BUILD)?(-$OPT)?)?
+ * $VNUM(-$PRE)?\+$BUILD(-$OPT)?
+ * $VNUM-$PRE(-$OPT)?
+ * $VNUM(+-$OPT)?
* </pre></blockquote>
*
* <p> where: </p>
@@ -1039,17 +1041,17 @@
* <li><p> <a name="pre">{@code $PRE}</a>, matching {@code ([a-zA-Z0-9]+)}
* --- A pre-release identifier. Typically {@code ea}, for a
* potentially unstable early-access release under active development,
- * or {@code internal}, for an internal developer build.
+ * or {@code internal}, for an internal developer build. </p></li>
*
* <li><p> <a name="build">{@code $BUILD}</a>, matching {@code
* (0|[1-9][0-9]*)} --- The build number, incremented for each promoted
* build. {@code $BUILD} is reset to {@code 1} when any portion of {@code
- * $VNUM} is incremented. </p>
+ * $VNUM} is incremented. </p></li>
*
* <li><p> <a name="opt">{@code $OPT}</a>, matching {@code
- * ([-a-zA-Z0-9\.]+)} --- Additional build information, if desired. In
+ * ([-a-zA-Z0-9.]+)} --- Additional build information, if desired. In
* the case of an {@code internal} build this will often contain the date
- * and time of the build. </p>
+ * and time of the build. </p></li>
*
* </ul>
*
@@ -1067,15 +1069,21 @@
*
* <p> A <em>short version string</em>, {@code $SVSTR}, often useful in
* less formal contexts, is a version number optionally followed by a
- * pre-release identifier:
+ * pre-release identifier:</p>
*
* <blockquote><pre>
* $VNUM(-$PRE)?
* </pre></blockquote>
*
+ * <p>This is a <a href="./doc-files/ValueBased.html">value-based</a>
+ * class; use of identity-sensitive operations (including reference equality
+ * ({@code ==}), identity hash code, or synchronization) on instances of
+ * {@code Version} may have unpredictable results and should be avoided.
+ * </p>
+ *
* @since 9
*/
- public static class Version
+ public static final class Version
implements Comparable<Version>
{
private final List<Integer> version;
@@ -1083,9 +1091,18 @@
private final Optional<Integer> build;
private final Optional<String> optional;
- Version(List<Integer> version, Optional<String> pre,
- Optional<Integer> build, Optional<String> optional) {
- this.version = Collections.unmodifiableList(version);
+ /*
+ * List of version number components passed to this constructor MUST
+ * be at least unmodifiable (ideally immutable). In the case on an
+ * unmodifiable list, the caller MUST hand the list over to this
+ * constructor and never change the underlying list.
+ */
+ private Version(List<Integer> unmodifiableListOfVersions,
+ Optional<String> pre,
+ Optional<Integer> build,
+ Optional<String> optional)
+ {
+ this.version = unmodifiableListOfVersions;
this.pre = pre;
this.build = build;
this.optional = optional;
@@ -1129,9 +1146,11 @@
+ s + "'");
// $VNUM is a dot-separated list of integers of arbitrary length
- List<Integer> version = new ArrayList<>();
- for (String i : m.group(VersionPattern.VNUM_GROUP).split("\\."))
- version.add(Integer.parseInt(i));
+ String[] split = m.group(VersionPattern.VNUM_GROUP).split("\\.");
+ Integer[] version = new Integer[split.length];
+ for (int i = 0; i < split.length; i++) {
+ version[i] = Integer.parseInt(split[i]);
+ }
Optional<String> pre = Optional.ofNullable(
m.group(VersionPattern.PRE_GROUP));
@@ -1158,7 +1177,7 @@
+ " build or optional components: '" + s + "'");
}
}
- return new Version(version, pre, build, optional);
+ return new Version(List.of(version), pre, build, optional);
}
private static boolean isSimpleNumber(String s) {
@@ -1269,9 +1288,7 @@
* During this comparison, a version with optional build information is
* considered to be greater than a version without one. </p>
*
- * <p> A version is not comparable to any other type of object.
- *
- * @param ob
+ * @param obj
* The object to be compared
*
* @return A negative integer, zero, or a positive integer if this
@@ -1282,8 +1299,8 @@
* If the given object is {@code null}
*/
@Override
- public int compareTo(Version ob) {
- return compare(ob, false);
+ public int compareTo(Version obj) {
+ return compare(obj, false);
}
/**
@@ -1294,9 +1311,10 @@
* described in {@link #compareTo(Version)} with the exception that the
* optional build information is always ignored. </p>
*
- * <p> A version is not comparable to any other type of object.
+ * <p> This method provides ordering which is consistent with
+ * {@code equalsIgnoreOptional()}. </p>
*
- * @param ob
+ * @param obj
* The object to be compared
*
* @return A negative integer, zero, or a positive integer if this
@@ -1306,47 +1324,47 @@
* @throws NullPointerException
* If the given object is {@code null}
*/
- public int compareToIgnoreOptional(Version ob) {
- return compare(ob, true);
+ public int compareToIgnoreOptional(Version obj) {
+ return compare(obj, true);
}
- private int compare(Version ob, boolean ignoreOpt) {
- if (ob == null)
- throw new NullPointerException("Invalid argument");
+ private int compare(Version obj, boolean ignoreOpt) {
+ if (obj == null)
+ throw new NullPointerException();
- int ret = compareVersion(ob);
+ int ret = compareVersion(obj);
if (ret != 0)
return ret;
- ret = comparePre(ob);
+ ret = comparePre(obj);
if (ret != 0)
return ret;
- ret = compareBuild(ob);
+ ret = compareBuild(obj);
if (ret != 0)
return ret;
if (!ignoreOpt)
- return compareOptional(ob);
+ return compareOptional(obj);
return 0;
}
- private int compareVersion(Version ob) {
+ private int compareVersion(Version obj) {
int size = version.size();
- int oSize = ob.version().size();
+ int oSize = obj.version().size();
int min = Math.min(size, oSize);
for (int i = 0; i < min; i++) {
int val = version.get(i);
- int oVal = ob.version().get(i);
+ int oVal = obj.version().get(i);
if (val != oVal)
return val - oVal;
}
return size - oSize;
}
- private int comparePre(Version ob) {
- Optional<String> oPre = ob.pre();
+ private int comparePre(Version obj) {
+ Optional<String> oPre = obj.pre();
if (!pre.isPresent()) {
if (oPre.isPresent())
return 1;
@@ -1368,8 +1386,8 @@
return 0;
}
- private int compareBuild(Version ob) {
- Optional<Integer> oBuild = ob.build();
+ private int compareBuild(Version obj) {
+ Optional<Integer> oBuild = obj.build();
if (oBuild.isPresent()) {
return (build.isPresent()
? build.get().compareTo(oBuild.get())
@@ -1380,8 +1398,8 @@
return 0;
}
- private int compareOptional(Version ob) {
- Optional<String> oOpt = ob.optional();
+ private int compareOptional(Version obj) {
+ Optional<String> oOpt = obj.optional();
if (!optional.isPresent()) {
if (oOpt.isPresent())
return -1;
@@ -1427,10 +1445,7 @@
* <p> Two {@code Version}s are equal if and only if they represent the
* same version string.
*
- * <p> This method satisfies the general contract of the {@link
- * Object#equals(Object) Object.equals} method. </p>
- *
- * @param ob
+ * @param obj
* The object to which this {@code Version} is to be compared
*
* @return {@code true} if, and only if, the given object is a {@code
@@ -1438,12 +1453,12 @@
*
*/
@Override
- public boolean equals(Object ob) {
- boolean ret = equalsIgnoreOptional(ob);
+ public boolean equals(Object obj) {
+ boolean ret = equalsIgnoreOptional(obj);
if (!ret)
return false;
- Version that = (Version)ob;
+ Version that = (Version)obj;
return (this.optional().equals(that.optional()));
}
@@ -1454,7 +1469,7 @@
* <p> Two {@code Version}s are equal if and only if they represent the
* same version string disregarding the optional build information.
*
- * @param ob
+ * @param obj
* The object to which this {@code Version} is to be compared
*
* @return {@code true} if, and only if, the given object is a {@code
@@ -1462,13 +1477,13 @@
* ignoring the optional build information
*
*/
- public boolean equalsIgnoreOptional(Object ob) {
- if (this == ob)
+ public boolean equalsIgnoreOptional(Object obj) {
+ if (this == obj)
return true;
- if (!(ob instanceof Version))
+ if (!(obj instanceof Version))
return false;
- Version that = (Version)ob;
+ Version that = (Version)obj;
return (this.version().equals(that.version())
&& this.pre().equals(that.pre())
&& this.build().equals(that.build()));
@@ -1477,9 +1492,6 @@
/**
* Returns the hash code of this version.
*
- * <p> This method satisfies the general contract of the {@link
- * Object#hashCode Object.hashCode} method.
- *
* @return The hashcode of this version
*/
@Override
@@ -1507,8 +1519,7 @@
private static final String BUILD
= "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
private static final String OPT = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
- private static final String VSTR_FORMAT
- = "^" + VNUM + PRE + BUILD + OPT + "$";
+ private static final String VSTR_FORMAT = VNUM + PRE + BUILD + OPT;
static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);