Jdk15 is really coming. Let’s take a look at its new features

brief introduction

The latest version of JDK twice a year, jdk15, was officially released on September 15, 2020. This jdk15 brings us many new features such as hidden classes, eddsa, pattern matching, records, closed classes and text block.

Let's have a look.

New features of jdk15

JEP 385 Deprecate RMI Activation for Removal

RMI activation is marked deprecate and will be removed in future releases.

RMI should be clear to everyone. RMI is remote method invocation, which is translated into Chinese as remote method invocation in jdk1 2.

RMI provides java with a powerful ability to develop distributed systems. The J2EE specification EJB uses RMI to realize the remote invocation of beans.

In RMI system, there are many distributed objects in the remote system. If these distributed objects are always active, they will occupy a lot of valuable system resources.

Therefore, RMI introduces a lazy activation method, which is called delayed activation.

There are two concepts, active object and passive object.

Active objects are remote objects that are instantiated and exposed in the JVM on some systems. Passive objects are objects that have not been instantiated (or exposed) in the JVM but can enter the active state.

The process of converting a passive object to an active object is called activation. Activation requires the object to be associated with the JVM, which may load the object's class into the JVM and restore the object to its previous state.

In RMI system, we use delayed activation. Deferred activation postpones the activation of an object until the first time it is used by the client (that is, the first method call).

Since RMI activation is so easy to use, why should it be abandoned?

For modern applications, most of the distributed systems are based on the web. The web server has solved the problems of passing through the firewall, filtering requests, authentication and security, and also provides many technologies of delayed loading.

Therefore, RMI activation is rarely used in modern applications. In addition, the code for RMI activation can hardly be found in various open source code bases.

In order to reduce the maintenance cost of RMI activation, RMI activation is set as optional in jdk8. Now in jdk15, it can finally be abandoned.

JEP 371 Hidden Classes

What are hidden classes?

Hidden classes are classes that cannot be directly used by the binary codes of other classes. Hidden classes are mainly used by some frameworks to generate runtime classes, but these classes are not used directly, but called through reflection mechanism.

Generally speaking, many languages based on JVM have the mechanism of dynamically generating classes, which can improve the flexibility and efficiency of the language.

For example, for the lambda expression introduced in jdk8, the JVM does not convert the lambda expression into a special class at compile time, but dynamically generates the corresponding class object from the corresponding bytecode at run time.

In addition, using dynamic proxy can also generate new dynamic classes for some classes.

So what characteristics do we want these dynamically generated classes to have?

However, the existing class definition APIs classloader:: defineclass and lookup:: defineclass are treated equally regardless of how the bytecode of the class is generated.

Therefore, we need some APIs to define hidden classes that cannot be found and have a limited life cycle. This will improve the efficiency of all JVM based language implementations.

For example:

java. lang.reflect. Proxy can define hidden classes as proxy classes that implement proxy interfaces.

java. lang.invoke. Stringconcatfactory can generate hidden classes to save constant connection methods;

java. lang.invoke. Lambdametafactory can generate hidden nestmate classes to accommodate lambda bodies accessing closed variables;

The JavaScript engine can generate hidden classes for bytecode converted from JavaScript programs, because these classes will be unloaded when the engine no longer uses them.

Ordinary classes are created by calling classloader:: defineclass, while hidden classes are created by calling lookup:: definehiddenclass.

This causes the JVM to derive a hidden class from the supplied bytes, link the hidden class, and return a lookup object that provides reflective access to the hidden class.

The caller can obtain the class object of the hidden class through the returned lookup object.

JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)

Eddsa elliptic curve signature algorithm is implemented.

I won't talk about the elliptic curve signature algorithm here. If you want to know more, you can leave me a message.

JEP 375 Pattern Matching for instanceof (Second Preview)

Pattern matching means that you can directly convert the type of the object when doing pattern matching.

Now this feature is a preview version.

Let's take a look at specific examples:

if (obj instanceof String) {
    String s = (String) obj;
    // use s
}

Before pattern matching, after we use instanceof, we also need to cast the object to use it.

However, after pattern matching, we can use:

if (obj instanceof String s) {
    // can use s here
} else {
    // can't use s here
}

Isn't it convenient.

JEP 384 Records (Second Preview)

Record is a lightweight class, which can be regarded as a data structure. It is similar to the case in scala.

Take an example of user customization to see how record is used:

public record Address(
        String addressName,String city
) {
}
public record CustUser(
        String firstName,String lastName,Address address,int age
) {}

Above, we defined two classes, custuser and address. Address is referenced in custuser.

The difference between record and ordinary class is that record has a defined field enclosed in parentheses.

The record class is final by default, and the fields in it are private final by default.

To know how record works, we can use javap to decompile the compiled class file and run javap custuser to get the following results:

警告: 二进制文件CustUser包含com.flydean.records.CustUser
Compiled from "CustUser.java"
public final class com.flydean.records.CustUser extends java.lang.Record {
  public com.flydean.records.CustUser(java.lang.String,java.lang.String,com.flydean.records.Address,int);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public java.lang.String firstName();
  public java.lang.String lastName();
  public com.flydean.records.Address address();
  public int age();
}

As you can see above, final class custuser inherits from Java lang.Record。

And the default constructor with all fields is automatically added. Each automatic acquisition method, and implements toString, hashcode and equals methods.

God, it's perfect. We have everything we want.

If the above javap is not very clear, you can open custuser. Com with the decompile function of the IDE Class file:

public final class CustUser extends java.lang.Record {
    private final java.lang.String firstName;
    private final java.lang.String lastName;
    private final com.flydean.records.Address address;
    private final int age;

    public CustUser(java.lang.String firstName,java.lang.String lastName,com.flydean.records.Address address,int age) { /* compiled code */ }

    public java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public java.lang.String firstName() { /* compiled code */ }

    public java.lang.String lastName() { /* compiled code */ }

    public com.flydean.records.Address address() { /* compiled code */ }

    public int age() { /* compiled code */ }
}

So we come to a shocking conclusion: record is immutable.

In the above example, we only use the contents in parentheses, and the braces are still empty. Can you add some methods or constructors like other normal classes?

The answer is yes.

Let's look at an overall plan:

public record CustUserWithBody(
        String firstName,int age
) {
    public String fullName(){
        return firstName+ lastName;
    }

    public CustUserWithBody{
        if (age < 18) {
            throw new IllegalArgumentException( "男大当婚,女大当嫁,18岁未到,不许出嫁!");
        }
    }
}

In the topic of record, we define a method and a constructor.

Look at this method first. In the method, we can access the variables defined in record, but don't try to modify them, because they are final, and you will get a mutation error.

Look at this constructor. This constructor has no curly braces but only curly braces. This constructor is called compact constructor. You cannot define a normal constructor in record because you will get a compilation error.

In this compact constructor, we can perform data verification on the defined fields. As mentioned above.

JEP 360 Sealed Classes (Preview)

In Java, the class hierarchy realizes code reuse through inheritance, and the methods of the parent class can be inherited by many subclasses.

However, the purpose of the class hierarchy is not always to reuse code. Sometimes, the purpose is to model the possibilities that exist in the domain, such as the shape type supported by the graphics library or the loan type supported by the financial application.

When using class hierarchies in this way, we may need to limit the set of subclasses to simplify modeling.

Because we have introduced sealed classes or interfaces, these classes or interfaces only allow the specified classes or interfaces to be extended and implemented.

for instance:

package com.example.geometry;

public abstract sealed class Shape
    permits Circle,Rectangle,Square {...}

In the above example, we specified that shape can only be inherited by circle and square.

The package name of the class is not specified in the above example. We can write as follows:

package com.example.geometry;

public abstract sealed class Shape 
    permits com.example.polar.Circle,com.example.quad.Rectangle,com.example.quad.simple.Square {...}

JEP 378 Text Blocks

Text blocks is to solve the problem of inputting multiple lines of data in Java.

For example:

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello,world</p>\n" +
              "    </body>\n" +
              "</html>\n";

It can be written as:


String html = """
              <html>
                  <body>
                      <p>Hello,world</p>
                  </body>
              </html>
              """;
String query = "SELECT \"EMP_ID\",\"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
               "WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
               "ORDER BY \"EMP_ID\",\"LAST_NAME\";\n";

It can be written as:


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

Very convenient.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>