Table of contents
1. New features of JDK concern
1.1 Build a learning environment
1.2.1.3 Static Method Static Method
1.2.1.4 Construction method of Record
1.2.1.6Record implementation interface
1.2.1.9 instanceof judges the Record type
1.2.2.1 Arrow expressions, new case tags
1.2.3.1 Recognizing text blocks
1.2.3.2 Text blocks are the same as ordinary double-quoted strings
1.2.4.1 var declares local variables
1. New features of JDK concern
1.1 Build a learning environment
JDK:JDK19
OpenJDK: https://jdk.java.net/19/ Liberica JDK: https://bell-sw.com/pages/downloads/ , is an OpenJDK distribution, which is cloud-native, Containers are especially optimized.
Maven: build and dependency management, version 3.6 or above
Configure local warehouse and Alibaba Cloud mirror
IDEA2022.3.1Ultimate: the main development tool, I am a 30-day trial version
Database: MySQL 5 or above
Firefox browser: use a relatively new version, the Chinese version.
Text tools: EditPlus, Sublime any.
1.2 Useful new features
JDK8-19 has added many new features. Here we will introduce the new features that are actually commonly used. Including the following aspects:
- Java Record
- Switch expression
- Text Block text block
- var declares a local variable
- sealed sealed class
1.2.1 Java Record
The new feature previewed in Java14 is called Record. In Java, Record is a special type of Java class. Can be used to create immutable classes with short syntax. See JEP 395. Jackson 2.12 supports the Record class.
Anytime a Java class is created, a lot of boilerplate code is created, we might do something like this:
- set and get methods for each field
- public constructor
- Override hashCode, toString(), equals() methods
Java Record avoids the above-mentioned boilerplate code, and has the following characteristics:
- Constructor with all parameters
- public accessor
- toString(),hashCode(),equals()
- No set, get method. Does not follow the bean naming convention
- The final class cannot inherit from Record, and Record is the final class of a hermit. Otherwise it is the same as normal class
- Immutable class, create Record by construction
- final attribute, cannot be modified
- Instance attributes cannot be declared, static members can be declared
IDEA creates a new Maven project Lesson01-feature
1.2.1.1 See how to use Record
IDEA creates a new Class and selects the class Record
step1: Create Student Record
public record Student(Integer id,String name,String email,Integer age) { }
step2: Create a Record object
public static void main(String[] args) {
Student lisi = new Student(1001, "lisi","[email protected]",20);
System.out.println("lisi = " + lisi.toString());
Student zhangsan = new Student(1002, "zhangsan","[email protected]",20);
System.out.println("zhangsan = " + zhangsan.toString());
System.out.println("lisi.equals(zhangsan) = " + lisi.equals(zhangsan));
System.out.println("lisi.name() = " + lisi.name());
System.out.println("zhangsan.name() = " + zhangsan.name());
}
Now you can see the console output:
lisi = Student[id=1001, name=lisi, [email protected], age=20] zhangsan = Student[id=1002, name=zhangsan, [email protected] , age=20] lisi.equals(zhangsan) = false lisi.name () = lisi zhangsan.name () = zhangsan
Record creates a read-only object through the constructor, which can read each property and cannot set new property values. Records are used to create immutable objects while reducing boilerplate code.
Record provides public accessors for each attribute, such as lisi.name ()
1.2.1.2 Instance Methods
Record is a Java class that defines methods like a normal Java class. The method concat is defined below to print out the name and age together. We create a common method concat to concatenate name and age into a string output.
step1: Create an instance method
public record Student(Integer id,String name,String email,Integer age) {
public String concat(){
return String.format("姓名:%s,年龄是:%d", this.name,this.age);
} }
step2: call the instance method
public static void main(String[] args) {
Student lisi = new Student(1001, "lisi","[email protected]",20);
String nameAndAge = lisi.concat();
System.out.println( nameAndAge);
}
Final console output: Name: lisi, age: 20
1.2.1.3 Static Method Static Method
The Record class defines static methods, and the use of static methods is the same as that of ordinary classes.
step1: Create a static method
public record Student(Integer id,String name,String email,Integer age) {
public String concat(){
return String.format("姓名:%s,年龄是:%d", this.name,this.age);
}
/** 静态方法 */
public static String emailUpperCase(String email){
return Optional.ofNullable(email).orElse("no email").toUpperCase();
} }
step2: Test the static method
public static void main(String[] args) {
String emailUpperCase = Student.emailUpperCase("[email protected]"); System.out.println("emailUpperCase = " + emailUpperCase);
}
1.2.1.4 Construction method of Record
We can add constructors to Record, there are three types of constructors: compact, standard and custom constructors
- The compact constructor doesn't have any parameters, not even parentheses.
- The canonical constructor takes all members as parameters
- The custom construction method is the number of custom parameters
step1: compact and custom construction methods
public record Student(Integer id,String name,String email,Integer age) { /紧凑构造方法/
public Student {
System.out.println("id"+ id );
if( id < 1 ){
throw new RuntimeException("ok");
}
}
/自定义构造方法/
public Student(Integer id, String name) {
this(id, name, null, null);
} }
step2: compile Student.java -> Student.class
public record Student(Integer id, String name, String email, Integer age) { /** 紧凑构造方法和规范构造方法合并了 */
public Student(Integer id, String name, String email, Integer age) {
System.out.println("id" + id);
if (id < 1) {
throw new RuntimeException("ok"); } else {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
} public Student(Integer id, String name) {
this(id, name, (String)null, (Integer)null);
} }
1.2.1.5 Record and Lombok
Java Records are a great way to create immutable classes and reduce boilerplate code. Lombok is a tool for reducing boilerplate code. The two have superficial overlaps. Some people may say that Java Record will replace Lombok. The two are tools with different purposes.
Lombok provides syntax convenience, and usually pre-installs some code templates, which are automatically executed according to the annotations you add to the class. Such libraries are purely for convenience in implementing POJO classes. By precompiling code. Add the template of the code to the class.
Java Record is a language level, a semantic feature, used for modeling, data aggregation. Simply put, it provides a common data class that acts as a "data carrier" for data transmission between classes and applications.
1.2.1.6Record implementation interface
Java Record can implement interfaces like ordinary classes, and rewrite methods of interfaces.
step1: Create a new interface and define a specification method.
public interface PrintInterface {
/** 输出自定义描述信息 */
void print(); }
step2: Create a new Record implementation interface, rewrite the method of the interface, and implement the business logic related to the current Record
public record ProductRecord(String id,String name,Integer qty)
implements PrintInterface {
@Override
public void print() {
String productDesc = String.join("-", id, name, qty.toString());
System.out.println("商品信息 = " + productDesc);
}
}
ProductRecord implements the print() method to print product details.
step3: Test the print method
public static void main(String[] args) {
ProductRecord product = new ProductRecord("P001", "手机", 100);
product.print();
}
1.2.1.7Local Record
Record can be used as a local object. Define and use Record in the code block, define a SaleRecord below
step1: Define Local Record
public static void main(String[] args) {
//定义Java Record
record SaleRecord(String saleId,String productName,Double money){};
//创建Local Record
SaleRecord saleRecord = new SaleRecord("S22020301", "手机", 3000.0);
//使用SaleRecord
System.out.println("销售记录 = " + saleRecord.toString()); }
Console output: Sales record = SaleRecord[saleId=S22020301, productName=mobile phone, money=3000.0]
1.2.1.8 Nested Records
Multiple Records can be defined in combination, and a Record can contain other Records. We define Record as Customer, which stores customer information, including two Records, Address and PhoneNumber
step1: Define Record
public record Address(String city,String address,String zipcode) {}
public record PhoneNumber(String areaCode,String number) {}
public record Customer(String id, String name, PhoneNumber phoneNumber, Address address) {}
step2: Create a Customer object
public static void main(String[] args) {
Address address = new Address("北京", "大兴区凉水河二街-8号10栋三层", "100176");
PhoneNumber phoneNumber = new PhoneNumber("010", "400-8080-105");
Customer customer = new Customer("C1001", "李项", phoneNumber, address);
System.out.println("客户 = " + customer.toString());
}
Console output: Customer = Customer[id=C1001, name=Li Xiang, phoneNumber=PhoneNumber[areaCode=010, number=400-8080-105], address=Address[city=Beijing, address=9 Liangshuihe Second Street, Daxing District 3rd Floor, Building No. 10, zipcode=100176]]
1.2.1.9 instanceof judges the Record type
instanceof can be used with Java Record. The compiler knows the exact number and type of record components.
step1: Declare Person Record with two attributes name and age
public record Person(String name,Integer age) { }
step2: When a business method judges that it is a Record type, continue to judge whether the age age meets 18 years old.
public class SomeService {
public boolean isEligible(Object obj){
// 判断obj为Person 记录类型
if( obj instanceof Person(String name, Integer age)){
return age >= 18;
}
return false; } }
instanceof can also be used in the following way
if( obj instanceof Person(String name, Integer age) person){
return person.age() >= 18; }
或者
if( obj instanceof Person p){
return p.age() >= 18; }
step3: test code
public static void main(String[] args) { SomeService service = new SomeService();
boolean flag = service.isEligible(new Person("李四", 20));
System.out.println("年龄符合吗?" + flag); }
Console output: The console output flag is true
Record is null in processing judgment
Java Record can automatically handle null.
step1: record is null
public static void main(String[] args) { SomeService service = new SomeService();
boolean eligible = service.isEligible(null);
System.out.println("年龄符合吗?" + eligible); }
The console output eligible is false, Debug debugs the code, and finds that the if statement is judged to be false and is not executed.
Summarize
- The abstract class java.lang.Record is the parent class of all Records.
- There are definitions for equals(), hashCode(), and toString() methods
- The Record class can implement java.io.Serializable serialization or deserialization
- Record supports generics, such as record Gif( T t ) { }
- The java.lang.Class class has two methods related to the Record class:
boolean isRecord() : Determine whether a class is a Record type RecordComponent[] getRecordComponents(): An array of Record, representing all record components of this record class
Customer customer = new Customer(....);
RecordComponent[] recordComponents = customer.getClass().getRecordComponents();
for (RecordComponent recordComponent : recordComponents) {
System.out.println("recordComponent = " + recordComponent);
}
boolean record = customer.getClass().isRecord();
System.out.println("record = " + record);
1.2.2 Switch
Three aspects of Switch, reference: JEP 361
- Arrow expressions are supported
- Support yield return value
- Support Java Record
1.2.2.1 Arrow expressions, new case tags
Switch new syntax, case label -> expression|throw statement|block
case label_1, label_2, ..., label_n -> expression;|throw-statement;|block
step1: new case label
week: Indicates Sunday (1) to Saturday (7), 1 and 7 are rest days, and others are working days. If other than 1-7, no date is required
public static void main(String[] args) {
int week = 7;
String memo = "";
switch (week){
case 1 -> memo = "星期日,休息";
case 2,3,4,5,6-> memo="工作日";
case 7 -> memo="星期六,休息";
default -> throw new IllegalArgumentException("无效的日期:");
}
System.out.println("week = " + memo);
}
1.2.2.2 Yeild return value
Yeild makes switch an expression that can return a value
grammar
variable = switch(value) { case v1: yield result value; case v2: yield result value; case v3,v4,v5.. yield result value }
Example: yield return value, jump out of switch block
public static void main(String[] args) {
int week = 2;
//yield是switch的返回值, yield跳出当前switch块
String memo = switch (week){ case 1: yield "星期日,休息";
case 2,3,4,5,6: yield "工作日";
case 7: yield "星期六,休息";
default: yield "无效日期"; };
System.out.println("week = " + memo);
}
No intermediate variables are needed, switch is calculated as an expression, and the result can be obtained. yield is the return value of the expression
Example: multiple expressions, case combined with yield
public static void main(String[] args) {
int week = 1;
//yield是switch的返回值, yield跳出当前switch块
String memo = switch (week){
case 1 ->{ System.out.println("week=1的 表达式部分");
yield "星期日,休息";
}
case 2,3,4,5,6 ->{
System.out.println("week=2,3,4,5,6的 表达式部分");
yield "工作日";
}
case 7 -> {
System.out.println("week=7的 表达式部分");
yield "星期六,休息";
}
default -> {
System.out.println("其他语句");
yield "无效日期";
}
};
System.out.println("week = " + memo);
}
hint:
case label -> and case label: cannot be mixed. One syntax format is used in a switch statement block. switch is used as an expression and assigned to a variable, which requires yield or case label -> expression. -> The expression on the right is the return value of the case.
Example:
public static void main(String[] args) {
int week = 1;
//yield是switch的返回值, yield跳出当前switch块
String memo = switch (week){
case 1 ->{
System.out.println("week=1的 表达式部分");
yield "星期日,休息";
}
case 2,3,4,5,6 ->{
System.out.println("week=2,3,4,5,6的 表达式部分");
yield "工作日";
}
case 7 -> "星期六,休息"; default -> "无效日期";
};
System.out.println("week = " + memo);
}
1.2.2.3 Java Record
Use record in switch expression, combined with case label -> expression, yield to realize complex calculation
step1: Prepare three Records
public record Line(int x,int y) {
}
public record Rectangle(int width,int height) {
}
public record Shape(int width,int height) {
}
step2: switch record
public static void main(String[] args) {
Line line = new Line(10,100);
Rectangle rectangle = new Rectangle(100,200);
Shape shape = new Shape(200,200);
Object obj = rectangle;
int result = switch (obj){
case Line(int x,int y) -> {
System.out.println("图形是线, X:"+x+",Y:"+y);
yield x+y;
}
case Rectangle(int w,int h) -> w * h;
case Shape(int w,int h) ->{ System.out.println("这是图形,要计算周长");
yield 2* (w + h);
}
default -> throw new IllegalStateException("无效的对象:" + obj);
};
System.out.println("result = " + result);
}
case Line, Rectangle, Shape Execute multiple statements in a code block, or arrow -> expression.
1.2.3 Text Block
Text Block is very convenient to process multi-line text, saving time and effort. There is no need to connect "+", single quotes, newlines, etc. Java 15, refer to JEP 378.
1.2.3.1 Recognizing text blocks
Syntax: Use a string enclosed in three double-quote characters.
"""
内容
"""
For example:
String name = """lisi"""; //Error 不能将文本块放在单行上
String name= """lisi 20""";
//Error 文本块的内容不能在没有中间行结束符的情况下跟随三个开头双引号
String myname= """
zhangsan 20
""";
//正确
Text block definitions require:
- A block of text begins with three double-quote characters, followed by a line terminator.
- Can't put text blocks on a single line
- The contents of a text block also cannot be followed by three opening double quotes without an intermediate line terminator
Three double quotes characters """ are treated the same as two double quotes "". They are used as normal strings. For example, equals(), "==", concatenated strings ("+"), as method parameters, etc.
1.2.3.2 Text blocks are the same as ordinary double-quoted strings
Text Block is used in the same way as ordinary strings, ==, equals comparison, and calling methods of the String class.
step1: string comparison and method
public void fun1() { String s1= """ lisi """; String s2 = """ lisi """;
//比较字符串 boolean b1 = s1.equals(s2); System.out.println("b1 = " + b1);
//使用 == 的比较 boolean b2 = s1 == s2; System.out.println("b2 = " + b2);
String msg = """ hello world"""; //字符串方法substring String sub = msg.substring(0, 5);
System.out.println("sub = " + sub); }
step2: output the result
b1 = true
b2 = true
sub = hello
1.2.3.3 Blank
- A detailed algorithmic description of whitespace handling is contained in JEP 378.
- Indentation in Text Block is automatically removed, left and right.
- To preserve left indentation, spaces. Move the content of the text block to the left (tab key)
Example:
public void fun2(){
//按tab向右移动,保留左侧空格
String html= """
动力节点,Java黄埔军校
""";
System.out.println( html);
}
Example 2: indent() method
public void fun3(){ String colors= """ red green blue """;
System.out.println( colors);
//indent(int space)包含缩进,space空格的数量 String indent = colors.indent(5);
System.out.println( indent);
}
output:
red
green
blue
red
green
blue
1.2.3.4 Text block methods
Text Block's format method formatted()
public void fun4(){
String info= """
Name:%s
Phone:%s
Age:%d
""".formatted("张三","13800000000",20);
System.out.println("info = " + info);
}
String stripIndent(): Remove the blanks at the beginning and end of each line
String translateEscapes() : convert escape sequences to string literals
1.2.3.5 Escape characters
The new escape character "\" represents a hermit newline character, which is escaped as a space by the Text Block. Common uses are to split very long string literals, concatenate multiple smaller substrings, and wrap multiple lines to generate strings. New escape character for combining very long strings.
example
public void fun5(){
String str= """
Spring Boot是一个快速开发框架 \
基于\"Spring\"框架,创建Spring应用 \
内嵌Web服务器,以jar或war方式运行 \
""";
System.out.println("str = " + str);
}
output
Spring Boot是一个快速开发框架 基于Spring框架,创建Spring应用 内嵌Web服务器,以jar或war方式运行
Summarize:
- For multi-line strings, Text Block should be used
- Recommended when Text Block can improve code clarity. For example, embedded SQL statements in the code
- Avoid unnecessary indentation, opening and closing sections.
- Use spaces or just tabs to indent text blocks.
- Mixing whitespace will result in irregular indentation.
- For most multiline strings, the delimiter is placed at the right end of the previous line, and the closing delimiter is placed on a separate line of the text block.
For example:
String colors= """
red
green
blue
""";
1.2.4 was
In JDK 10 and above, you can use the var identifier to declare a local variable with a non-null initializer, which can help you write concise code, eliminate redundant information and make the code more readable, use it with caution.
1.2.4.1 var declares local variables
var features
- var is a reserved word, not a keyword (var can be declared as a variable name)
- Local variables declared in the method must have an initial value
- Each time a variable is declared, multiple variables cannot be compounded. var s1="Hello", age=20; //Error
- The dynamic type of var is that the compiler infers the type based on the value assigned to the variable
- var replaces the display type, the code is concise, and unnecessary typesetting and confusion are reduced.
Advantages and disadvantages of var
- The code is concise and tidy.
- Reduced program readability (no strongly typed declarations)
Example:
//通常
try (Stream<Customer> result = dbconn.executeQuery(query)) {
//...
//推荐
try (var customers = dbconn.executeQuery(query)) {
//...
}
比较 Stream<Customer> result 与 var customers
1.2.4.2 Use var when using
- simple temporary variable
- Complex, multi-step logic, nested expressions, etc., short variables help to understand the code
- Ability to determine variable initial values
- When the variable type is relatively long
Example:
public void fun1(){
var s1="lisi";
var age = 20;
for(var i=0;i<10;i++){
System.out.println("i = " + i);
}
List<String> strings = Arrays.asList("a", "b", "c");
for (var str: strings){
System.out.println("str = " + str);
}
}
1.2.5 sealed
sealed is translated as sealed. Sealed Classes was first proposed in JEP 360 of Java15, and previewed again in JEP 397 of Java 16, and became a formal function in JEP 409 of Java 17.
The main feature of Sealed Classes is to restrict inheritance
The main feature of Sealed Classes is to limit inheritance. In Java, inheritance is enhanced to extend the capabilities of classes and reuse certain functions. When this ability is out of control. Contrary to the design of the original class, resulting in unforeseen abnormal logic.
Sealed Classes limit unlimited expansion.
There is already a sealed design in Java
- final keyword, the modified class cannot be inherited
- private restricts private classes
sealed as a keyword can be used on class and interface, combined with the permits keyword. Define a sealed class that restricts inheritance
1.2.5.1 Sealed Classes
sealed class class name permits subclass 1, subclass N list {}
step1:: declare sealed Class
public sealed class Shape permits Circle, Square, Rectangle {
private Integer width;
private Integer height;
public void draw(){
System.out.println("=======Shape图形======");
}
}
permits means allowed subclasses, one or more.
step2:: Declare subclasses
There are three types of subclass declarations
- final end, still sealed
- The sealed subclass is a sealed class and needs to be implemented by the subclass
- non-sealed non-sealed class, extended use, unlimited
Example:
//第一种 final
public final class Circle extends Shape {
}
//第二种 sealed class
public sealed class Square extends Shape permits RoundSquare {
@Override public void draw() { System.out.println("=Square图形");
} }
//密封类的子类的子类
public final class RoundSquare extends Square{
}
//非密封类 , 可以被扩展。放弃密封
public non-sealed class Rectangle extends Shape {
}
//继承非密封类
public class Line extends Rectangle{
}
Sealed classes do not support anonymous classes and functional interfaces
1.2.5.2 Sealed Interface
The sealing interface is the same as the sealing type
step1: Declare the sealed interface
public sealed interface SomeService permits SomeServiceImpl {
void doThing();
}
step2: implement the interface
public final class SomeServiceImpl implements SomeService {
@Override
public void doThing() {
}
}
The above classes and interfaces must be in the same package accessible range.