Java has now developed to Java13 (official version), I believe many friends are still not familiar with each version, this special Java9 to Java13 each version of some new features to do some detailed explanation. I have also found a lot on the Internet, but most of them are official documentation CV, without any code demo, and the official code is not easy to find, the official API is still Java10, the official documentation is really a mess. So I wrote a special article here, mainly for the usual development and related functions Java9 to Java13 each version of the code has done a detailed explanation.

[PS] : This season is too cold, the south is wet and cold, my hands are born chilblains, see in the last few days of the year, there is no way, I finally choose to go to the Internet cafe spent a few days, network fees are spent several hundred pieces, in order to create this dry goods at the cost of the next ah. Finally worked on the article for several days. Every syntax detail is demonstrated by example, and I made a point of downloading each version of the Open JDK to experience the details and new features.

I hope you can like, comment and favorites three times, also live up to my pains, thank you.

Want to get more dry goods, welcome everyone to pay more attention to my blog. This article is the author of AWeiLoveAndroid original, unauthorized, strictly prohibited reprint.


A Java. 9

[note:] Java9 has the most updates, and this requires special attention.

Java 9 Collection factory method

Example:

public static void main(String[] args) {
  Set<String> set = Set.of("set1"."set2"."set3");
  // set: [set1, set3, set2]
  System.out.println("set: " + set);
       
  Map<String, String> maps1 = Map.of(
     "map1"."Apple"."map2"."Orange"."map3"."Banana"."map4"."cherry");
  // maps1: {map3=Banana, map2=Orange, map1=Apple, map4=cherry}        
  System.out.println("maps1: " + maps1);
    
  Map<String, String> maps2 = Map.ofEntries (
           new AbstractMap.SimpleEntry<>("map1"."Apple"),
           new AbstractMap.SimpleEntry<>("map2"."Orange"),
           new AbstractMap.SimpleEntry<>("map3"."Banana"),
           new AbstractMap.SimpleEntry<>("map4"."cherry"),
           new AbstractMap.SimpleEntry<>("map5"."Apple"),
           new AbstractMap.SimpleEntry<>("map6"."Orange"),
           new AbstractMap.SimpleEntry<>("map7"."Banana"),
           new AbstractMap.SimpleEntry<>("map8"."cherry"),
           new AbstractMap.SimpleEntry<>("map9"."Apple"),
           new AbstractMap.SimpleEntry<>("map10"."Orange"),
           new AbstractMap.SimpleEntry<>("map11"."Banana"),
           new AbstractMap.SimpleEntry<>("map12"."cherry")); // maps2: {map3=Banana, map2=Orange, map1=Apple, map12=cherry, map11=Banana, map10=Orange, // map9=Apple, map8=cherry, map7=Banana, map6=Orange, map5=Apple, map4=cherry} System.out.println("maps2: " + maps2);
}
Copy the code

Java9 previously did:

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");

Map<String, String> map = new HashMap<>();
map.put("A"."Apple");
map.put("B"."Boy");
map.put("C"."Cat");
Copy the code

Java9 can print the contents of a collection directly; previously, you had to traverse the collection to get all of its elements. This is a big improvement.

Static factory methods are added to the Java 9 List, Set, and Map interfaces to create immutable instances of these collections.

In Java 9, you can create collection objects of List, Set, and Map using the following methods. There are many overloaded methods as shown in the following example:

static <E> List<E> of()
static <E> List<E> of(E e1)
static <E> List<E> of(E e1, E e2)
static <E> List<E> of(E e1, E e2, E e3)
static <E> List<E> of(E e1, E e2, E e3, E e4)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
static <E> List<E> of(E... elements)

static <E> Set<E> of()
static <E> Set<E> of(E e1)
static <E> Set<E> of(E e1, E e2)
static <E> Set<E> of(E e1, E e2, E e3)
static <E> Set<E> of(E e1, E e2, E e3, E e4)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
static <E> Set<E> of(E... elements)


static <K, V> Map<K, V> of() 
static <K, V> Map<K, V> of(K k1, V v1)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
                               K k6, V v6)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
                               K k6, V v6, K k7, V v7)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
                               K k6, V v6, K k7, V v7, K k8, V v8)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
                               K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9)
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
                               K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10)
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries)
Copy the code

List, Set, and Map interfaces, of(…) Method overloads different methods with 0 to 10 arguments. Map interfaces with more than 10 parameters can use ofEntries(…) Methods.

REPL (JShell)

REPL(Read Eval Print Loop) means interactive programming environment. JShell is an interactive programming environment tool added to Java 9. It allows you to execute Java statements without using class or method wrappers. It is similar to the Python interpreter in that you can type expressions directly and see the result of their execution.

Such as:

Enter “jshell” to open the jshell command window:

Enter /help to view the help information:

Perform operations, create and use functions, and exit:

The interface supports private and private static methods:

Here is a comparison of the interface changes between Java8 and java9:

The following is an example:

interface Test{
    String fields = "interface field";

    public abstract void abstractMethods();

    default void defaultMethods() {
        System.out.println("default Method");
        staticMethods();
        privateMethods();
        privateStaticMethods();
     }

    static void staticMethods() {
        System.out.println("static Method");
     }

    private void privateMethods() {
        System.out.println("private Method");
    }
   
    private static void privateStaticMethods() {
        System.out.println("private Static Method"); }}Copy the code

Interface implementation class:

public class TestImpl implements Test{

    @Override
    public void abstractMethods() {
        System.out.println("abstract Method"); }}Copy the code

The test class:

public class Demo{
    public static void main(String[] args) {
        TestImpl testImpl = new TestImpl();
        System.out.println(testImpl.fields);
        testImpl.abstractMethods();
        testImpl.defaultMethods(); }}Copy the code

Test results:

interface field
abstract Method
default Method
static Method
private Method
private Static Method
Copy the code

Improved Stream API and Optional classes

Java 9’s improved Stream API added several new methods for Stream: dropWhile, takeWhile, and ofNullable. It also added an overload method for iterate to make Stream handling easier.

The Optional class was introduced in Java8 to handle null pointer exceptions. In Java 9, the stream(), ifPresentOrElse(), and OR () methods were added to improve its functionality.

The following is an example:

Stream.of("a"."b"."c".""."e"."f").takeWhile(s->! s.isEmpty()) .forEach(System.out::print);
System.out.println();
Stream.of("10"."20"."30".""."40"."50").dropWhile(s-> ! s.isEmpty()) .forEach(System.out::print);
System.out.println();
IntStream.iterate(3, x -> x < 10, x -> x+ 3).forEach(System.out::print);
System.out.println();
System.out.println(Stream.ofNullable(100).count());
System.out.println(Stream.ofNullable(null).count());
Copy the code

Results:

// abc
// 4050
// 369
// 1
// 0
Copy the code
Public static void main(String[] args) {// stream() usage: List<Optional<String>> List = array.asList (Optional. Of ("data1"), 
        Optional.empty(), 
        Optional.of("data2"),
        Optional.empty(),
        Optional.of("data3")); List<String> result = list.stream() .flatMap(Optional::stream) .collect(Collectors.toList()); // result [data1, data2, data3] system.out.println (result); //ifPresentOrElse uses: Optional<String> Optional = Optional. Of ("datas"); // Result Value: datas optional. IfPresentOrElse (x -> system.out.println ("Value: " + x),() -> 
    System.out.println("No data found")); optional = Optional.empty(); // Result No data found optional. IfPresentOrElse (x -> system.out.println ("Value: " + x),() -> 
  System.out.println("No data found"));

    Optional<String> optional1 = Optional.of("datas");
    Supplier<Optional<String>> nullData = () -> Optional.of("No data found");
    optional1 = optional1.or(nullData);
    // Value: datas
    optional1.ifPresent( x -> System.out.println("Value: " + x));

    optional1 = Optional.empty();    
    optional1 = optional1.or(nullData);
    // Value: No data found
    optional1.ifPresent( x -> System.out.println("Value: " + x));

}
Copy the code

Improved CompletableFuture API

Delays and timeouts support, improved support for subclasses, new factory methods:

Public CompletableFuture

completeOnTimeout(T value, long timeout, TimeUnit unit) : In a timeout (unit in Java. Util. Concurrent. Timeunits units, such as MILLISECONDS) to the given value to complete the CompletableFutrue before. Return this CompletableFutrue.

Public CompletableFuture

orTimeout(long timeout, TimeUnit unit) : If there is no finish, in the given timeout in Java. Util. Concurrent. Complete this CompletableFutrue TimeoutException, and returns the CompletableFutrue.

Public CompletableFuture newIncompleteFuture() : Makes the CompletableFuture easier to inherit

CompletionStage completedStage(U value) : Returns a new CompletionStage completed with the specified value, and supports only the interfaces within the CompletionStage.

CompletionStage failedStage(Throwable ex) : Returns a new CompletionStage completed with the specified exception, and supports only the interfaces within the CompletionStage.

Exception handling mechanism improved try-with-Resources

Try-with-resources declarations have been improved in JDK 9. If you already have a resource that is final or its equivalent, you can use that variable in the try-with-resources statement without declaring a new variable in the try-with-resources statement.

The following is an example:

public static void main(String[] args) throws IOException {
  System.out.println(readData("test")); / / the result:test
}

static String readData(String message) throws IOException { Reader inputString = new StringReader(message); BufferedReader br = new BufferedReader(inputString); // try (BufferedReader br1 = br)return br1.readLine();
    // }
    // Java9处理方式:
    try (br) {
      returnbr.readLine(); }}Copy the code

Improved @deprecated annotation

Annotations in Java 9 add two new elements: since and forRemoval. Since: Element specifies the deprecated version of the annotated API element. ForRemoval: element Indicates that the ANNOTATION API element will be removed in a future release and the API should be migrated. The following is an example:

@Deprecated(since = "1.9".forRemoval = true)
class Test{
}
Copy the code

Diamond Operator (Diamond Operator “<>”)

In Java 9, “<>” can be used with anonymous inner classes to improve code readability.

Example:

public class Test {
   public static void main(String[] args) {
      Handler<Integer> intHandler = new Handler<>(1) {
         @Override
         public void handle() { System.out.println(content); }}; intHandler.handle(); Handler<? extends Number> intHandler1 = new Handler<>(2) { @Override public voidhandle() {
            System.out.println(content);
         }
      };
      intHandler1.handle();
      Handler<?> handler = new Handler<>("test") {
         @Override
         public void handle() { System.out.println(content); }}; handler.handle(); } } abstract class Handler<T> { public T content; public Handler(T content) { this.content = content; } abstract void handle(); }Copy the code

In java8, the <> after the newHandler<> in the above example must have a generic type inside it. Java9 does not.

Unicode 7.0 extensions support:

From Java SE 9, upgrade the existing platform API to support Unicode 7.0, mainly in the following classes:

Java.lang.Character and Java.lang.String Java.text packages for Bidi, BreakIterator and Normalizer This upgrade will include improved bidirectional behavior, This allows for a better display of texts such as Arabic and Hebrew introduced in Unicode 6.3. Unicode 7.0 itself will add about three thousand characters and two dozen scripts.

More details, please see: openjdk.java.net/projects/jd…


Second, the Java 10

Here’s a look at some of the features we developers can experience directly:

Var Local variable type inference

Example:

var list = new ArrayList<String>(); ArrayList<String> var stream = list.stream(); / / represents the Stream < String >Copy the code

This processing will be limited to local variables with initializers, indexes in enhanced for loops, and local variables declared in traditional for loops. It does not apply to variable declarations of method form, constructor form, method return type, field, catch form, or any other type.

Unicode 8.0 is supported.

Enhancements to java.util.locale and related apis to implement other Unicode extensions to the BCP 47 language tag.

The BCP 47 language tag extensions include:

  • Cu (Currency type)
  • Fw (First day of the week)
  • Rg (Area coverage)
  • Tz (Time zone)

Specific API changes are:

  • Java. Text. The DateFormat: : get * Instance will return to Instance based on extension ca, rg and/or tz
  • Java. Text. DateFormatSymbols: : getInstance will return to instance based on extension rg
  • Java. Text. The DecimalFormatSymbols: : getInstance will return to instance based on extension rg
  • Java. Text. NumberFormat: : get * Instance will return to Instance based on extension nu and/or rg
  • Java. Time. The format. DateTimeFormatter: : localizedBy returns DateTimeFormatter based on ca extended case, rg and/or tz
  • Java. Time. The format. DateTimeFormatterBuilder: : getLocalizedDateTimePattern according to rg extension pattern string.
  • Java. Time. The format. DecimalStyle: : of the DecimalStyle according to extension returns the instance nu, and/or the rg
  • Java. Time. Temporal. WeekFields: : of the WeekFields according to rg extension fw and/or returned instance
  • Java. Util. Calendar: : {getFirstDayOfWeek, getMinimalDaysInWeek} will be based on extension fw rg and/or return values
  • Java. Util. Currency: : getInstance Currency according to the extension cu and/or returns the instance rg
  • Java. Util. Locale: : getDisplayName will return a string, including the U extension display name
  • Java. Util. Spi. LocaleNameProvider these U extension will have a new key and the types of spi

Other features are related to garbage collection, compilers, certificates, and command tools, which are not listed here.

More details, please see: openjdk.java.net/projects/jd…


Third, the Java 11

Syntax lambda arguments for local variables

Lambda expressions in Java11 can be implicitly typed, where the formal parameters of the type can be inferred. For formal arguments to implicitly typed lambda expressions, the reserved type name var is allowed so that: (var x, var y) -> x.rocess (y) is equivalent to:

(x, y) -> x.croess (y) -> x.croess (yCopy the code

Other lambda uses are the same as lambda uses in Java8.

Start a single file source code program

Enhance the Java launcher to run programs provided as a single file of Java source code, including using the program from within the script through “shebang” files and related techniques.

Starting with JDK 10, Java initiators run in one of three modes: starting class files, starting the main class of JAR files, or starting the main class of modules. Here, we have added a new fourth mode: start classes declared in the source file.

If Class Name identifies an existing file with a. Java extension, select the source file mode, and compile and run the file. The –source option can be used to specify the source version of the source code.

If the file does not have a. Java extension, then –source must use this option to enforce the source file schema. For example, when the source file is a “script” to execute and the name of the source file does not follow the normal naming convention for Java source files.

More details, please see: openjdk.java.net/projects/jd…


Fourth, the Java 12

Extend the switch statement:

Extend the switch statement so that it can be used as a statement or an expression, and both forms can use “traditional” or “simplified” scoping and control the behavior of the flow. These changes will simplify everyday coding in Switch. This is the preview feature in JDK 12.

Please note: This JEP has been replaced by JEP 354 in JDK 13.

Common writing:

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
Copy the code

Now we introduce a new form of the switch tag, written as “case L ->”, which means that only the code to the right of the tag will be executed if the tag matches. For example, you can now write old code:

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}
Copy the code

Another example of a local variable is written like this:

int numLetters;
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        numLetters = 6;
        break;
    case TUESDAY:
        numLetters = 7;
        break;
    case THURSDAY:
    case SATURDAY:
        numLetters = 8;
        break;
    case WEDNESDAY:
        numLetters = 9;
        break;
    default:
        throw new IllegalStateException("Wat: " + day);
}
Copy the code

It is now written like this:

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};
Copy the code

More details, please see: openjdk.java.net/projects/jd…


Five, the Java 13

Switch expression preview

New in JDK 13 is the Switch expression Beta, which is an enhanced version of the Java12 switch expression functionality, and the switch expression update in Java13 can be used in production environments. Switch expressions extend switch statements to be used not only as statements but also as expressions, and both can be written using traditional Switch syntax.

In addition to the Java12 usage, the update to Java13 introduces a new keyword, yield. Most switch expressions have an expression on the right side of the “Case L ->” switch label. If a complete block is required, the yield statement is used to produce a value that is the value of the enclosing switch expression.

Example:

int j = switch (day) {
    case MONDAY  -> 0;
    caseTUESDAY -> 1; default -> { int k = day.toString().length(); int result = f(k); yield result; }};Copy the code

The above example could also use the traditional switch statement:

int result = switch (s) {
    case "Foo": 
        yield 1;
    case "Bar":
        yield 2;
    default:
        System.out.println("Neither Foo nor Bar, hmmm...");
        yield 0;
};
Copy the code

The situation expressed by the switch must be detailed; There must be a matching switch label for all possible values. (Obviously, switch declarations don’t have to be detailed.) This usually means that a default clause is required. But enum switch For expressions that overwrite all known constants, the default compiler inserts a clause to indicate that the enum definition has changed between compile time and run time. Relying on this implicit default clause insertion can make your code more robust. Now, when you recompile the code, the compiler checks to see if all cases are handled explicitly.

In addition, the switch expression must complete normally with a value, or it must complete suddenly by throwing an exception. This has many consequences. First, the compiler checks each switch label for a match, and then produces a value.

Example:

int i = switch (day) {
    case MONDAY -> {
        System.out.println("Monday"); 
        // ERROR! Block doesn't contain a yield statement } default -> 1; }; i = switch (day) { case MONDAY, TUESDAY, WEDNESDAY: yield 0; default: System.out.println("Second half of the week"); // ERROR! Group doesn't contain a yield statement
};
Copy the code

Another consequence is that control statements, break, yield, return, and continue, fail to jump switch expressions, as shown in the following example:

z: 
    for (int i = 0; i < MAX_VALUE; ++i) {
        int k = switch (e) { 
            case 0:  
                yield 1;
            case 1:
                yield 2;
            default: 
                continuez; // ERROR! Illegal jump through a switch expression }; . }Copy the code

Text Blocks preview

Simply put: strings can be displayed across multiple lines without escaping characters. The goal is to improve the readability of strings in Java programs that represent code written in non-Java languages, while avoiding escape sequences that are common.

In Java, embed AN HTML, XML, SQL, or JSON fragment “…” in a string literal. It usually takes a lot of editing to escape and concatenate before the code that contains the code block can be compiled. The code is often difficult to read and maintain. But Java13’s code block capability will make strings more intuitive and can span multiple lines without the visual clutter of escaping, which will improve the readability and writability of Java programs. Essentially a two-dimensional block of text, not a one-dimensional sequence of characters.

Basic syntax:

"""
line 1
line 2
line 3
"""
Copy the code

Line 1\nline 2\nline 3\n”

Or concatenation of string characters:

"line 1\n" +
"line 2\n" +
"line 3\n"
Copy the code

If a line terminator is not required at the end of the string, you can place the end delimiter on the last line of the content. For example, a text block:

"""
line 1
line 2
line 3"""
Copy the code

Specific use:

I’m going to write HTML code inside the string,

Before Java13:

String html = "<html>\n" +
              " \n" +
              " 

Hello, world

\n"
+ " \n" + "</html>\n"; Copy the code

Java13 writing:

String html = """   

Hello, world

"
""; Copy the code

Another example is SQL:

Before Java13:

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
               "WHERE `CITY` = 'INDIANAPOLIS'\n" +
               "ORDER BY `EMP_ID`, `LAST_NAME`; \n";
Copy the code

Java13 writing:

String query = """ SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` WHERE `CITY` = 'INDIANAPOLIS' ORDER BY `EMP_ID`, `LAST_NAME`; """;
               
Copy the code

Such as:

Before Java13:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {\n" +
                         " print('\"Hello, world\"'); \n" +
                         "}\n" +
                         "\n" +
                         "hello(); \n");
                         
Copy the code

Java13 writing:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval(""" function hello() { print('"Hello, world"'); } hello(); """);

Copy the code

More details, please see: openjdk.java.net/projects/jd…