Recently, a release candidate for Java 10 took place, and an article appeared on Habré, which lists the JEPs included in the new release. However, not all Java changes get their JEP. In particular, small additions to the standard library almost always occur without JEPs. At the same time, they are often even more practical than they are from the more serious changes that have been rewarded by JEP. Let's see what has been added to the standard library of Java 10.
Quite often it is necessary to convert character sequences in byte sequences and backwards in one form or another, for which you have to specify an encoding. Historically, the encoding was specified as a text string (for example, "UTF-8"
). In this case, any method that took such a string could throw an UnsupportedEncodingException
, because you never know what you can pass in the string. However, most often you are only worried about one encoding, which is always there (like the same UTF-8). And the exception, unfortunately, is verifiable. In this case, what to do in the exception handler is not very clear to many. As a result, catch-blocks appear that do not carry meaning and pollute the code. Anyway, string literals in the middle of the code are not the best idea.
Starting with Java 7, the situation is changing. First, the StandardCharsets class appeared with constants like UTF_8
, US_ASCII
, etc. Support for the corresponding encodings is guaranteed by any Java implementation on any platform. Secondly, pairwise methods began to appear slowly, accepting a Charset object instead of a string. This process was continued in Java 10, adding new constructors to the PrintWriter , PrintStream , Formatter and Scanner classes, as well as new overloaded methods ByteArrayOutputStream.toString (Charset) (yes!), URLEncoder.encode (String, Charset) (yes !!), URLDecoder.decode (String, Charset) (yes !!!). NewReader (ReadableByteChannel, Charset) and newWriter (WritableByteChannel, Charset) were added to the Channels class, as well as Properties.storeToXML (OutputStream, String, Charset) . For a number of methods, the checked exceptions in the signature have disappeared altogether, which greatly simplifies their use (including in lambda expressions).
Java 9 introduced the InputStream.transferTo (OutputStream) method, which allows you to easily stream the contents of the InputStream
into the OutputStream
. The logical continuation of this is the Reader.transferTo (Writer) method, which does the same for character streams.
As part of the transition to releases, the Runtime.Version class, which appeared in Java 9, was updated at regular intervals. If someone missed, this is now the official way of working with Java versions — parsing the version string, comparing versions, etc. reworked the format and value of the component version, focusing on major.minor.security in the main part. For example, if you have Java 9.0.1, then 9 is the major version, 0 is the minor version, and 1 is the security update. This is reflected in the class method names. In the top ten it was decided that the ideal was still not reached and the meaning would be different: feature.interim.update.patch (if there is no patch, then it is considered 0). As a result, the old methods are marked obsolete, although they lived only half a year, and new ones appeared - feature () , interim () , update () , patch () .
The development of another API, which appeared in Java 9 - StackWalker . There is a method StackFrame.getMethodType () , which returns a MethodType object from the java.lang.invoke API and StackFrame.getDescriptor () , which returns a method handle in a virtual machine format. Now you can distinguish in frames methods with the same name, but with a different signature. Until now, this could only be done with getLineNumber()
, which is unreliable and works only with debug information.
This is quite an important internal improvement to the java.lang.invoke API as part of the Constant Dynamic implementation. Now the MethodHandle.invokeWithArguments method can take any number of arguments (and not only 251) if the target method is a vararg method (with a variable number of arguments). As part of the work on it, another method MethodType.lastParameterType () appeared , which returns the type of the last parameter (just a parameter with a type of ellipsis like String...
in the case of a vararg method). Of course, lastParameterType can be useful in other cases, if you are working with java.lang.invoke.
The O_DIRECT option is a mode for working with files in Linux, whereby the use of caching is disabled whenever possible. This option is useful for database systems and other products that are actively working with large files. Often, such products implement their own caching system, which works better because they know the structure of the file and can predict which parts of it will be needed in the future. In this case, caching from the operating system only hinders.
Initially, to support this mode, it was proposed to introduce new constructors FileInputStream / FileOutputStream, but in the process of discussion came to a new constant O_DIRECT in com.sun.nio.file.ExtendedOpenOption . Yes, yes, com.sun! This is an officially unsupported class (it is in the jdk.unsupported module). It is surprising that in this package there are new features. And in the java.base module, the FileStore.getBlockSize () method has appeared, which returns the block size on the device. This information is very useful if you are organizing cached file access yourself.
In the updated Unicode standard, the locale string can encode not only such familiar things as language or decimal point instead of a comma, but also a whole bunch, for example, time zone, currency or which day of the week to be considered first. Java now also supports (and this, by the way, JEP !) It took a small change in the API. In particular, the methods getDisplayUnicodeExtensionKey and getDisplayUnicodeExtensionType have been added to the LocaleNameProvider class for human output of information about these extensions in this locale.
The interaction of new unicode extensions with DateTimeFormatter has led to an interesting effect. There was already a method withLocale
, which simply set the output format.
And here it turns out that the Locale
object can also switch the time zone. As a result, for example, withZone(zone).withLocale(locale)
and withLocale(locale).withZone(zone)
can create a different formatter. We decided that if withLocale
could silently switch the time zone inside the formatter, this would be too unexpected, so the existing method was decided not to change (it is still responsible only for the language, the format of the numbers, etc.). Instead, they added a new method - localizedBy , which already can switch both the time zone and the first day of the week.
Together with the Stream API in Java 8, classes appeared like IntSummaryStatistics to count the number, amount, minimum, maximum and average values at the same time. As it turned out, it is not at all easy to restore the state of such an object, if for some reason you need to continue collecting statistics from a certain place. In Java 10, this oversight is fixed: there are constructors like IntSummaryStatistics (long count, int min, int max, long sum) that allow you to restore the state.
These changes will probably be the most useful. Recall that in Java 9 there were methods for creating immutable collections like List.of (...), allowing you to construct a list and set from an explicit set of elements or an array. In Java 10, a new family of methods has been added - List.copyOf , Set.copyOf, and Map.copyOf , which construct an immutable collection from the collection. Of course, if an immutable collection has already been submitted to the input, then there will be no extra copying. This approach has long been familiar to users of the Guava library: this method should be called, giving the collection to untrusted hands, or keeping it in the field for a long time in order not to accidentally change it.
This change also adds new collectors to the Stream API: toUnmodifiableList , toUnmodifiableSet, and toUnmodifiableMap . It is curious that in the previously existing toList
, toSet
and toMap
no one guaranteed variability. Therefore, it was possible, without violating the specification, to simply change them, returning the immutable collection. However, of course, if you allow people to do something (in this case, change the collection), many will immediately lay down on this behavior. Now to change collectors like toList
to immutable would mean breaking a lot of code. One could say that the authors of this code are themselves to blame, but still for Java compatibility is the cornerstone.
Note that both copyOf
methods and new collectors do not tolerate nulls as elements of a collection (for Map, both in keys and values). Therefore, blindly cramming new methods into existing code can be dangerous.
Somewhat strange thing, in my opinion. Stuart Marx, the author of the Optional class, has long been displeased with the fact that people are too abused by the get()
method, although it is supposed to be used in exceptional cases rather than everywhere. Even when Nine didn’t come out, Stewart suggested zadreprekatit and replace it with some getWhenPresent()
, so that people would not stretch their hands to call him (the long name always likes less). Then he met serious community resistance, but did not give up his attempts. The final solution is to add a new orElseThrow () method (without parameters), which is identical in meaning to the get()
method and at the same time get()
not deprecated, but simply add a note that it is desirable to use the new method. In principle, orElseThrow()
without parameters looks logical: it is like orElseThrow
with a parameter, just throw some default exception. However, in my opinion, this will add even more mess, because some people will use the old method, and some - the new one.
In Java 8, the SplittableRandom class appeared - a new pseudo-random number generator, which is faster than Random, does not synchronize, produces significantly better pseudo-random numbers and can divide into two generators, which is useful for parallel streams. It is curious that it does not extend the Random
class, such as SecureRandom
or ThreadLocalRandom
, which reduces its usefulness: many APIs already take a Random
argument. However, most of the methods for SplittableRandom
and Random
same. This problem is still waiting to be resolved, and in Java 10 they fixed a small flaw: there was no SplittableRandom.nextBytes method, although there is an analogue to Random
.
StampedLock is a rather interesting synchronization primitive, which allows, for example, to avoid locks in many cases when reading several fields simultaneously and create fair locks only with intensive competitive updates. The idea is quite simple: you are given a stamp before the operation, then you read the fields and check the stamp. If it is not rotten, then everything is fine, no one tried to update in parallel, and the read fields really correspond to the atomic state. Otherwise, you can try again or go to the normal lock. To optimize some usage scenarios, new methods have been added to it that allow us to check what a stamp we have in our hands: isWriteLockStamp , isReadLockStamp , isLockStamp , isOptimisticReadStamp .
Another refinement of a big feature introduced in Java 9: Multi-Release JARs. Let me remind you that this is an opportunity to have several versions of the same class or resource in the same JAR file corresponding to a different version of Java. In developing this functionality, of course, the JarFile
and JarEntry
classes have been updated. Now we have added two new methods - this is JarEntry.getRealName () , which returns the real name of the file (for example, not foo
, but META-INF/versions/9/foo
) and JarFile.versionedStream () , which returns a stream of JAR file, related to the current version only.
Unfortunately, the standard library for the desktop practically does not develop, only cosmetic changes.
In Java 9, some classes like Event were disabled. However, it turned out that not everything can be done without using them. In particular, Toolkit.getMenuShortcutKeyMask returns a bitmask using constants from the Event class. Now added a modern alternative - Toolkit.getMenuShortcutKeyMaskEx () .
Path2D is, by and large, a mutable list (a la ArrayList) of two-dimensional points indicating the method of connection between them (straight line, quadratic or cubic spline). As in ArrayList, it is reasonable to have a trimToSize method that allows you to trim the internal array to the real number of points, saving memory if you plan to keep this path for a long time without modification. The subtlety is that Path2D is an abstract class that is not tied to the type of coordinates — it can be float
or double
, for which there are concrete implementations of Path2D.Float
and Path2D.Double
. But nothing prevented someone from creating a separate implementation of an abstract class that does not inherit the existing ones (usually this is not necessary, but you never know). And now a new abstract method has been added to it, with the result that such a third-party implementation will no longer compile when switching to Java 10. Why it was impossible to make an empty trimToSize
in an abstract class is not clear to me. I think the quality of code review in java.desktop is lower than in java.base.
As part of the bugfix of one muddy drop in the depths of the logic of the switchable buttons, the getGroup method was brought to the ButtonModel interface (they did it here normally - the method has a default implementation). In the standard library, all implementations of this interface inherit the DefaultButtonModel , in which such a method already existed. Well, it's nice that now you don’t need to cast the interface. It's funny that setGroup
already in the interface, but getGroup
not.
A small, nice addition is the RuntimeMXBean.getPid () method for getting the PID of the current Java machine process. People used to do something like Long.parseLong(mbean.getName().split("@")[0])
. Now it is not necessary.
If you are monitoring the state of the system, you may not always need full stack traces of all threads. Now the ThreadMXBean.dumpAllThreads and ThreadMXBean.getThreadInfo methods have an overloaded version with an additional parameter - the maximum depth of the setrays. This can seriously improve the performance of monitoring, because in enterprise systems one can often see a thousand threads with stack traces more than a hundred frames deep, and it takes a lot of time to turn this from internal virtual machine records into Java objects.
A new mode of working with sockets has appeared - ExtendedSocketOptions.TCP_QUICKACK . In C, you have long been able to use it to speed up connection, now you can do it in Java without squats. What is bad is the usual ACK - explains John Nagle (yes, the same one ).
There are a few more new methods in the modules jdk.compiler, java.compiler, javafx.controls and jdk.packager.services, but the bulk is listed above. Of course, there are not so many changes as you usually expect in the major version of Java, well, the version comes out six months after the previous one. Getting used to the new rhythm of life.
Source: https://habr.com/ru/post/349868/
All Articles