目录
前言
Java12
1.switch表达式
2.低延迟垃圾回收器Shenandoah
Java13
1.文本块升级
Java14
1.更优雅的instanceof
2.Record记录类
Java15
1.Sealed密封类
Java16
Java17
前言
上一篇文章和大家分享的是 Java9~Java11 的常用新特性,这篇就再和大家分享一下 Java12~Java17 部分常用的新特性吧。
Java12
1.switch表达式
新的 switch-case 语法最早出现于 Java12,而在 Java12 和 Java13 中都是预览特性,在 Java14 中才成为了标准特性。
传统的 switch-case,我们需要去写 break,否则就会发生穿透现象;而新的 switch-case 不用再写 break了,同时 switch-case 也成了一个表达式,我们能够定义变量去拿到 switch-case 的返回值。
下面的代码是新旧 switch-case 的语法,案例如下:⬇️⬇️⬇️
package com.alibaba.one; import java.util.Scanner; public class SwitchTest { private static Scanner input = new Scanner(System.in); private static void oldSwitchCase() { System.out.print("请输入汽车代号:"); int carCode = input.nextInt(); switch (carCode) { case 1: System.out.println("奔驰"); break; case 2: System.out.println("宝马"); break; case 3: System.out.println("奥迪"); break; // 可选 default: System.out.println("未知"); break; } } private static void newSwitchCase() { System.out.print("请输入汽车代号:"); int carCode = input.nextInt(); switch (carCode) { case 1 -> System.out.println("奔驰"); case 2 -> System.out.println("宝马"); case 3 -> System.out.println("奥迪"); // 可选 default -> System.out.println("未知"); } } private static void newSwitchCase2() { System.out.print("请输入汽车代号:"); int carCode = input.nextInt(); String carBrand = switch (carCode) { case 1 -> "奔驰"; case 2 -> "宝马"; case 3 -> "奥迪"; // 必选 default -> "未知"; }; System.out.println(carBrand); } private static void newSwitchCase3() { System.out.print("请输入汽车代号:"); int carCode = input.nextInt(); String carBrand = switch (carCode) { case 1, 2, 3 -> "一线豪华品牌"; case 4, 5 -> "二线豪华品牌"; // 必选 default -> "未知"; }; System.out.println(carBrand); } public static void main(String[] args) { oldSwitchCase(); newSwitchCase(); newSwitchCase2(); newSwitchCase3(); } } /* 请输入汽车代号:1 奔驰 请输入汽车代号:2 宝马 请输入汽车代号:3 奥迪 请输入汽车代号:4 二线豪华品牌 */2.低延迟垃圾回收器Shenandoah
这个低延迟垃圾回收器 Shenandoah 在 Java12 中还是实验特性,在 Java15 中成为了标准特性。
下面把尚硅谷谷姐的图拿过来给大家参考,有兴趣的可以去了解一下这些GC ⬇️⬇️⬇️
Java13
1.文本块升级
新的文本块写法最早出现于 Java13,而在 Java13、Java14 中都是预览特性,在 Java15中才成为标准特性。
新的文本块使用三个双引号"""作为开始和结束分隔符,开始分隔符后面不能跟内容,更多针对的是 JSON、XML、SQL语句拼接等;
文本块会自动去除每行开头和结尾的非必要空格,如需保留,需要使用 \s 转义;
相对缩进会被保留,文本块内部行终止符会被保留,如果想要显式消除行终止符,需要使用 \ 转义。
案例如下:⬇️⬇️⬇️
package com.alibaba.three; public class TextBlockTest { private static void beforeJava15TextBlock() { String json = "{\n" + " \"name\": \"张三\",\n" + " \"age\": 25,\n" + " \"hobby\": [\"睡觉\", \"吃饭\"]\n" + "}"; System.out.println(json); } private static void afterJava15TextBlock() { // \s表示空格 String json = """ { "name": "张三",\s\s "age": 25, "hobby": ["睡觉", "吃饭"] }"""; System.out.println(json); } public static void main(String[] args) { beforeJava15TextBlock(); afterJava15TextBlock(); } } /* { "name": "张三", "age": 25, "hobby": ["睡觉", "吃饭"] } { "name": "张三", "age": 25, "hobby": ["睡觉", "吃饭"] } */Java14
1.更优雅的instanceof
instanceof 类型匹配的新语法最早出现于 Java14,是预览特性,而在 Java16中才成为标准特性。
案例如下:⬇️⬇️⬇️
package com.alibaba.two; public abstract class Animal { public abstract void eat(); }package com.alibaba.two; public class Cat extends Animal { @Override public void eat() { System.out.println("猫在吃小鱼..."); } public void catchMouse() { System.out.println("抓老鼠..."); } }package com.alibaba.two; public class Dog extends Animal { @Override public void eat() { System.out.println("狗在啃骨头..."); } public void watchDoor() { System.out.println("看大门..."); } }package com.alibaba.two; import java.util.Scanner; public class InstanceOfTest { private static Scanner input = new Scanner(System.in); public static void beforeJava16InstanceOf() { System.out.print("请输入动物种类:"); String animalType = input.next(); Animal animal = switch (animalType) { case "cat" -> new Cat(); case "dog" -> new Dog(); default -> null; }; if (null != animal) { animal.eat(); if (animal instanceof Cat) { Cat cat = (Cat) animal; cat.catchMouse(); } else if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.watchDoor(); } } } public static void afterJava16InstanceOf() { System.out.print("请输入动物种类:"); String animalType = input.next(); Animal animal = switch (animalType) { case "cat" -> new Cat(); case "dog" -> new Dog(); default -> null; }; if (null != animal) { animal.eat(); if (animal instanceof Cat cat) { cat.catchMouse(); } else if (animal instanceof Dog dog) { dog.watchDoor(); } } } public static void main(String[] args) { beforeJava16InstanceOf(); afterJava16InstanceOf(); } } /* 请输入动物种类:cat 猫在吃小鱼... 抓老鼠... 请输入动物种类:dog 狗在啃骨头... 看大门... */2.Record记录类
Record 记录类的新语法最早出现于 Java14,是预览特性,而在 Java16中才成为标准特性。
基本语法是:
public record 记录类名(实例变量列表) { // 可选:自定义方法、静态变量 }记录类会生成:为每个实例变量加上 private final 修饰、全参构造、get方法(方法名不带get)、equals、hashCode、toString方法。
案例如下:⬇️⬇️⬇️
package com.alibaba.four; public record Employee(String name, Integer age, String email) { /** * 已包含如下代码: * private final String name; * private final Integer age; * private final String email; * 全参构造 * get方法,注意这里的方法名是不带get的,直接就是变量名 * equals、hashCode、toString方法 */ // 如果要自定义额外的代码逻辑,举例如下: public static final Integer MAX_VALUE = Integer.MAX_VALUE; public Employee { // 以下判断只是针对记录类而言,实际对入参的判断建议使用校验注解@NotBlank、@NotNull、@Min、@Max等 if (null == name || name.isEmpty()) { throw new IllegalArgumentException("姓名不能为空:" + name); } if (age < 0) { throw new IllegalArgumentException("年龄不能为负数:" + age); } if (null == email || !email.contains("@")) { throw new IllegalArgumentException("邮箱地址不合法:" + email); } } public boolean isAdult() { return age >= 18; } @Override public String toString() { return String.format("Employee(name = %s, age = %d)", name(), age()); } }package com.alibaba.four; public class RecordTest { public static void main(String[] args) { Employee employee1 = new Employee("张三", 25, "123@qq.com"); Employee employee2 = new Employee("李四", 17, "888@163.com"); System.out.println(employee1.name()); System.out.println(employee1.age()); System.out.println(employee1.email()); System.out.println(employee2.isAdult()); System.out.println(employee1.equals(employee2)); System.out.println(employee2); System.out.println(Employee.MAX_VALUE); } } /* 张三 25 123@qq.com false false Employee(name = 李四, age = 17) 2147483647 */Java15
1.Sealed密封类
Sealed 密封类最早出现于 Java15,是预览特性,而在 Java17中才成为标准特性。
基本语法是:
public sealed class 密封类名 [可选 extends 父类 implements 接口] permits 子类1, 子类2, 子类3 { // 代码逻辑 }密封类是指定该类只能被你指定的这些子类继承,同时密封类的直接子类必须使用 sealed、non-sealed、final 的其中一个去修饰(sealed 继续密封、non-sealed 解除密封、final 最终)。
- 如果密封类A的子类B采用 sealed 修饰,那么这个子类B仍然是密封类,需继续按照密封类的约束去编写;
- 如果密封类A的子类B采用 non-sealed 修饰,那么这个子类B解除密封,继承子类B的其他子类没有任何约束,直接 public class 即可,和普通类一致。
- 如果密封类A的子类B采用 final 修饰,那么这个子类B不能被任何类继承。
案例如下:⬇️⬇️⬇️
package com.alibaba.five; /** * sealed密封限制,指定MercedesBenz, BMW, Audi三个类才可以继承 */ public abstract sealed class Car permits MercedesBenz, BMW, Audi { public abstract void highPerformance(); }package com.alibaba.five; /** * final不能再被继承 */ public final class MercedesBenz extends Car { @Override public void highPerformance() { System.out.println("MercedesBenz AMG E63"); } }package com.alibaba.five; /** * non-sealed解除密封限制,可以被任意public class的类继承 */ public non-sealed class BMW extends Car { @Override public void highPerformance() { System.out.println("BMW M5"); } }package com.alibaba.five; /** * sealed继续保持密封,指定谁才可以继承 */ public sealed class Audi extends Car permits YiQiAudi { @Override public void highPerformance() { System.out.println("Audi RS7"); } }package com.alibaba.five; public final class YiQiAudi extends Audi { }package com.alibaba.five; import java.util.ArrayList; import java.util.List; public class SealedTest { public static void main(String[] args) { List<Car> cars = new ArrayList<>(); cars.add(new MercedesBenz()); cars.add(new BMW()); cars.add(new Audi()); for (Car car : cars) { car.highPerformance(); } Audi audi = new YiQiAudi(); System.out.println(audi); } } /* MercedesBenz AMG E63 BMW M5 Audi RS7 com.alibaba.five.YiQiAudi@6d311334 */那么到此,我们就见识到 Java 中有这些类:
- 普通类 public class
- 最终类 final class
- 抽象类 abstract class(包含 public interface)
- 枚举类 public enum
- 注解类 public @interface
- 记录类 public record
- 密封类 public sealed class
Java16
Java16 主要就是将 Java14 中的 Record 记录类、instanceof、打包工具 jpackage 这些预览特性变成了标准特性,所以大家直接参考上面的 Java14即可。
Java17
Java17 首先将 Java15 中的 Sealed 密封类从预览特性变成了标准特性。
那么针对 Java17 了话,在之前的版本中,很多常用的、不错的特性发展到这里都已经成为了标准特性、稳定的功能,所以如果大家想使用这些功能,建议大家直接安装 jdk17 就可以了,因为未来这个版本也将会是一个主流。
那么分享到这里就结束了,大家学习这些新特性的时候更多的针对(Java8、Java17、Java21)这三个版本就可以了。