JavaRush /Java Blog /Random EN /From 8 to 13: A complete overview of Java versions. Part ...

From 8 to 13: A complete overview of Java versions. Part 1

Published in the Random EN group
Kittens, hello everyone)) So, today we are in 2020, and there is very little left until the release of Java 14. You should expect the finished version on March 17, we’ll analyze what’s fresh and interesting there after the fact, but today I’d like to refresh my memory on previous versions of Java. What new did they bring us? Let's get a look. Let's start the review with Java 8, since it is still quite relevant and is used in most projects. From 8 to 13: a complete overview of Java versions.  Part 1 - 1Previously, new versions were released every 3-5 years, but recently Oracle has taken a different approach - “new Java every six months.” And so, every six months we see the release of features. Whether it’s good or bad, everyone sees it differently. For example, I don’t like this very much, since new versions do not have many new features, but at the same time, versions are growing like mushrooms after rain. I blinked a couple of times on a project with Java 8, and Java 16 was already released (but when it comes out rarely, new features accumulate, and in the end this event is long-awaited, like a holiday: everyone is discussing the new goodies and you can’t pass by it) . So let's get started!

Java 8

Functional Interface

What is this? A functional interface is an interface that contains one unimplemented (abstract) method. @FunctionalInterface is an optional annotation that is placed above such an interface. Needed to check whether it meets the requirements of a functional interface (having only one abstract method). But as always, we have some caveats: default and static methods do not fall under these requirements. Therefore, there can be several such methods + one abstract one, and the interface will be functional. It may also contain methods of the Object class that do not affect the definition of the interface as functional. I'll add a few words about default and static methods:
  1. Methods with the default modifier allow you to add new methods to interfaces without breaking their existing implementation.

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    Yes, yes, we add the implemented method to the interface, and when implementing this method, you can not override it, but use it as an inherited one. But if a class implements two interfaces with a given method, we will have a compilation error, and if it implements interfaces and inherits a class with a certain identical method, the parent class method will overlap the interface methods and the exception will not work.

  2. static methods in an interface work the same as static methods in a class. Don’t forget: you cannot inherit static methods, just as you cannot call a static method from a descendant class.

So, a few more words about functional interfaces and let’s move on. Here are the main lists of FIs (the rest are their varieties):

    Predicate - takes some value T as an argument, returns boolean.

    Example:boolean someMethod(T t);

  • Consumer - takes an argument of type T, returns nothing (void).

    Example:void someMethod(T t);

  • Supplier - takes nothing as input, but returns some value T.

    Example:T someMethod();

  • Function - takes a parameter of type T as input, returns a value of type R.

    Example:R someMethod(T t);

  • UnaryOperator - takes a T argument and returns a value of type T.

    Example:T someMethod(T t);

Stream

Streams are a way to handle data structures in a functional style. Typically these are collections (but you can use them in other, less common situations). In more understandable language, Stream is a data stream that we process as if working with all the data at the same time, and not brute force, as with for-each. Let's look at a small example. Let's assume we have a set of numbers that we want to filter (less than 50), increase by 5, and output the first 4 numbers from the remaining ones to the console. How would we have done this earlier:
List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);

int count = 0;

for (int x : list) {

  if (x >= 50) continue;

  x += 5;

  count++;

  if (count > 4) break;

  System.out.print(x);

}
There doesn't seem to be much code, and the logic is already a little confusing. Let's see how it will look using the stream:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Streams greatly simplify life by reducing the amount of code and making it more readable. For those who want to delve into this topic in more detail, here is a good (I would even say excellent) article on this topic .

Lambda

Perhaps the most important and long-awaited feature is the appearance of lambdas. What is lambda? This is a block of code that can be passed around to different places so it can be executed later as many times as needed. Sounds pretty confusing, doesn't it? Simply put, using lambdas, you can implement a method of a functional interface (a kind of implementation of an anonymous class):
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
We implemented the run() method quickly and without unnecessary red tape. And yes: Runnable is a functional interface. I also use lambdas when working with streams (as in the examples with streams above). We won’t go too deep, since you can dive quite deep, I’ll leave a couple of links so that guys who are still diggers at heart can dig deeper:

foreach

Java 8 has a new foreach that works with a data stream like a stream. Here's an example:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(analogous to someList.stream().foreach(…))

Method reference

Reference methods are a new, useful syntax designed to reference existing methods or constructors of Java classes or objects via :: Method references come in four types:
  1. Link to the designer:

    SomeObject obj = SomeObject::new

  2. Static method reference:

    SomeObject::someStaticMethod

  3. A reference to a non-static method of an object of a certain type:

    SomeObject::someMethod

  4. A reference to a regular (non-static) method of a specific object

    obj::someMethod

Often, method references are used in streams instead of lambdas (reference methods are faster than lambdas, but are inferior in readability).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
For those who want more information on reference methods:

API Time

There is a new library for working with dates and times - java.time. From 8 to 13: a complete overview of Java versions.  Part 1 - 2The new API is similar to any Joda-Time. The most significant sections of this API are:
  • LocalDate is a specific date, as an example - 2010-01-09;
  • LocalTime - time taking into account the time zone - 19:45:55 (analogous to LocalDate);
  • LocalDateTime - combo LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - represents time zones;
  • Clock - using this type you can access the current time and date.
Here are a couple of really interesting articles on this topic:

Optional

This is a new class in the java.util package , a value wrapper whose trick is that it can also safely contain null . Receiving optional: If we pass nullOptional<String> someOptional = Optional.of("Something"); in Optional.of , we will get our favorite NullPointerException . For such cases they use: - in this method you don’t have to be afraid of null. Next, create an initially empty Optional: To check if it is empty, use: will return true or false to us. Perform a certain action if there is a value, and do nothing if there is no value: A reverse method that returns the passed value if Optional is empty (sort of a backup plan): You can continue for a very, very long time (fortunately, Optional has added methods with both generous hands), but we won’t dwell on this. It’s better for me to leave a couple of links for starters: Optional<String> someOptional = Optional.ofNullable("Something");Optional<String> someOptional = Optional.empty();someOptional.isPresent();someOptional.ifPresent(System.out::println);System.out.println(someOptional.orElse("Some default content")); We went over the most famous innovations in Java 8 - that's not all. If you want to know more, then I left this for you:

Java 9

So, on September 21, 2017, the world saw JDK 9. This Java 9 comes with a rich set of features. While there are no new language concepts, the new APIs and diagnostic commands will definitely be of interest to developers. From 8 to 13: a complete overview of Java versions.  Part 1 - 4

JShell (REPL - read-eval-print loop)

This is a Java implementation of an interactive console that is used to test functionality and use different constructs in the console, such as interfaces, classes, enums, operators, etc. To launch JShell, you just need to write jshell in the terminal. Then we can write whatever our imagination allows: From 8 to 13: a complete overview of Java versions.  Part 1 - 5Using JShell, you can create top-level methods and use them within the same session. The methods will work just like static methods, except that the static keyword can be omitted. Read more in the Java 9. REPL (JShell) manual .

Private

Starting with version 9 of Java, we have the opportunity to use private methods in interfaces (default and static methods, since we simply cannot override others due to insufficient access). private static void someMethod(){} try-with-resources The ability to handle Try-With-Resources exceptions has been upgraded:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Modularity ( Jigsaw )

A module is a group of related packages and resources along with a new module descriptor file. This approach is used to loosen the coupling of code. Loose coupling is a key factor for code maintainability and extensibility. Modularity is implemented at different levels:
  1. Programming language.
  2. Virtual machine.
  3. Standard java API.
JDK 9 comes with 92 modules: we can use them or create our own. Here are a couple of links for a deeper look:

Immutable Collection

In Java 9, it became possible to create and fill a collection with one line, while making it immutable (previously, to create an immutable collection, we needed to create a collection, fill it with data, and call a method, for example, Collections.unmodifiableList). An example of such a creation: List someList = List.of("first","second","third");

Other innovations:

  • expanded Optional (new methods added);
  • the ProcessHandle and ProcessHandle interfaces appeared to control the actions of the operating system;
  • G1 - default garbage collector;
  • HTTP client with support for both HTTP/2 protocols and WebSocket;
  • expanded Stream;
  • added Reactive Streams API framework (for reactive programming);
For a more complete immersion in Java 9, I advise you to read:

Java 10

So, six months after the release of Java 9, in March 2018 (I remember it like yesterday), Java 10 came onto the scene. From 8 to 13: a complete overview of Java versions.  Part 1 - 6

var

Now we don't have to provide a data type. We mark the message as var and the compiler determines the type of the message by the type of the initializer present on the right. This feature is only available for local variables with an initializer: it cannot be used for method arguments, return types, etc., since there is no initializer to be able to define the type. Example var (for type String):
var message = "Some message…..";
System.out.println(message);
var is not a keyword: it is essentially a reserved type name, just like int . The benefit of var is great: type declarations take up a lot of attention without bringing any benefit, and this feature will save time. But at the same time, if a variable is obtained from a long chain of methods, the code becomes less readable, since it is immediately unclear what kind of object lies there. Dedicated to those who want to become more familiar with this functionality:

JIT compiler (GraalVM)

Without further ado, let me remind you that when you run the javac command, the Java application is compiled from Java code into JVM bytecode, which is the binary representation of the application. But a regular computer processor cannot simply execute the JVM bytecode. For your JVM program to work, you need another compiler for this bytecode, which is converted into machine code that the processor is already able to use. Compared to javac, this compiler is much more complex, but also produces higher quality machine code. Currently, OpenJDK contains the HotSpot virtual machine, which in turn has two main JIT compilers. The first, C1 ( client compiler ), is designed for higher speed operation, but code optimization suffers. The second is C2 (server compiler). The execution speed suffers, but the code is more optimized. When is which one used? C1 is great for desktop applications where long JIT pauses are undesirable, and C2 is great for long-running server programs where spending more time on compilation is quite bearable. Multi-level compilation is when the compilation first goes through C1, and the result goes through C2 (used for greater optimization). GraalVM is a project created to completely replace HotSpot. We can think of Graal as several related projects: a new JIT compiler for HotSpot and a new polyglot virtual machine. The peculiarity of this JIT compiler is that it is written in Java. The advantage of the Graal compiler is safety, that is, not crashes, but exceptions, not memory leaks. We will also have good IDE support, and we will be able to use debuggers, profilers or other convenient tools. In addition, the compiler may well be independent of HotSpot, and it will be able to create a faster JIT-compiled version of itself. For diggers:

Parallel G1

The G1 garbage collector is certainly cool, no doubt about it, but it also has a weak point: it performs a single-threaded full GC cycle. At a time when you need all the power of hardware you can muster to find unused objects, we are limited to a single thread. Java 10 fixed this. Now the GC now works with all the resources we add to it (that is, it becomes multi-threaded). To achieve this, the language developers have improved the isolation of the main sources from GC, creating a nice clean interface for GC. The developers of this cuteness, OpenJDK, had to specifically clean up the dump in the code in order not only to simplify the creation of new GCs as much as possible, but also to make it possible to quickly disable unnecessary GCs from the assembly. One of the main criteria for success is the absence of a drawdown in operating speed after all these improvements. Let's look also: Other innovations:
  1. A clean Garbage-Collector Interface is introduced. This improves the isolation of source code from different garbage collectors, making it possible to integrate alternative collectors quickly and painlessly;
  2. Combining JDK sources into one repository;
  3. Collections received a new method - copyOf (Collection) , which returns an immutable copy of this collection;
  4. Optional (and its variants) has a new method .orElseThrow() ;
  5. From now on, JVMs are aware that they are running in a Docker container and will retrieve container-specific configuration rather than querying the operating system itself.
Here are some more materials for a more detailed introduction to Java 10: I used to be very confused by the fact that some versions of Java were called 1.x. I'd like to be clear: Java versions prior to 9 simply had a different naming scheme. For example, Java 8 can also be called 1.8 , Java 5 - 1.5 , etc. And now we see that with the transition to releases from Java 9, the naming scheme has also changed, and Java versions are no longer prefixed with 1.x. This is the end of the first part: we went over the new interesting features of java 8-10. Let's continue our acquaintance with the latest in the next post .
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION