jdk14 新特性

Java14新特性

1. instanceof 模式匹配

旧:类型匹配后的使用,需要强制转换

private static void old(Object obj) {
    if(obj instanceof String){
        String str = (String)obj;
        System.out.println(str.contain("java"));
    }else{
        System.out.println("error");
    }
}

新:类型匹配过程中就可以完成转换,并且定义变量str

private static void New(Object obj) {
    if(obj instanceof String str){
        System.out.println("无需强制转换");
    }else{
        System.out.println("error");
    }
}

注意:str变量只能在它所在if中使用

private static void New(Object obj) {
    if(obj instanceof String str){
        System.out.println("无需强制转换");
    }else{
        System.out.println(str.contains("java"));
        System.out.println("error");
    }
}

这样写是错误的。

2. 实用的NullPointerException

该特性改进了空指针异常的可读性,能更准确地给出null变量的信息。

回顾Java8,提供了Optional来处理空指针异常。

举例:

class Bank{
    private Customer customer;

    public Bank(Customer customer) {
        this.customer = customer;
    }
    public Bank(){}
    public Customer getCustomer(){
        return customer;
    }
    public void setCustomer(Customer customer){
        this.customer = customer;
    }
}

class Customer{
    private Account account;

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public Customer(Account account) {
        this.account = account;
    }
    public Customer() {
    }

}

class Account{
    private int balance;

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    public Account(int balance) {
        this.balance = balance;
    }
}

main方法:

public class Test02 {
    public static void main(String[] args) {
        Bank bank = new Bank(new Customer());
        bank.getCustomer().getAccount().getBalance();
    }
}

很明显我们没有实例化 Account对象,这个代码bank.getCustomer().getAccount()运行会报空指针

运行看看结果:

Exception in thread "main" java.lang.NullPointerException
	at NullPointerException.Test02.main(Test02.java:6)

的确有报错,但是没有给出具体哪儿报错了。

接下来我们在VM options加个指令:-XX:+ShowCodeDetailsInExceptionMessages

再运行看看结果:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "NullPointerException.Account.getBalance()" because the return value of "NullPointerException.Customer.getAccount()" is null
	at NullPointerException.Test02.main(Test02.java:6)

这样就显示出详细报错信息了。

3. Record(预览特性)

Java语言架构师Brian Goetz吐槽Java语言太啰嗦,有太多重复的,容易出错的代码,如构造函数、getter/setter等。

Java14 也许最令人兴奋的,同时也是最令人惊讶的创新就是:Record类型的引入!

使用record来减少类声明语法,效果类似lombok的的@Data注解。

它们的个共同的是类的部分或全部状态可以直接在类头中描述。

和枚举类一样,记录也是类的一种受限形式。

举例

原来定义一个实体类

public final class User {
    private final String name;
    private final User partner;

    public User(String name, User partner) {
        this.name = name;
        this.partner = partner;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return name.equals(user.name) &&
                partner.equals(user.partner);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, partner);
    }

    public String getName() {
        return name;
    }

    public User getPartner() {
        return partner;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", partner=" + partner +
                '}';
    }
}

需要这么多代码,虽然IDE可以自动生成,但是我们浏览的时候就显得很复杂。

Java14提供了一种Record创建类的方式

在这里插入图片描述

现在只需要这样创建:

public record Person(String name,Person partner) {
	//成员变量定义在头部
}

测试

public static void main(String[] args) {
    //测试构造器
    Person p1 = new Person("Romio",new Person("Julia",null));
    System.out.println(p1);
}

##输出
Person[name=Romio, partner=Person[name=Julia, partner=null]]
相当于record提供了toString方法

我们查看一下Person的字节码文件:

public final class Person extends java.lang.Record {
    private final java.lang.String name;
    private final Record.Person partner;

    public Person(java.lang.String name, Record.Person partner) { /* 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 name() { /* compiled code */ } //相当于getName()方法

    public Record.Person partner() { /* compiled code */ } //相当于getPartner()方法
}

注意事项:

  • 我们还可以在Record声明的类中定义静态字段、静态方法、构造器或实例方法

  • 不能在Record声明的类中定义非静态实例字段;类不能声明为abstract;不能声明显式的父类等。

public record Person(String name,Person partner) {

    //静态属性
    public static String nation;

    //静态方法
    public static String showNation(){
        return nation;
    }
    //构造器
    public Person(String name){
        this(name,null);
    }
    //实例方法
    public String getNameToUpperCase(){
        return name.toUpperCase();
    }

}
  • 因为record声明默认为final类,类不能被继承,类成员变量不可被更改(即set方法)

不合法:

abstract record A{  //不可用abstract修饰
    
}
record B() extends Thread{ //不可继承其他类,因为record隐式继承了Record父类,由于Java的单继承,不可再显示继承其他父类。
}

值得一提:Java.lang.Class对象中添加了两个新方法:

RecordComponent[] getRecordComponents()
boolean isRecord()

用于反射的使用

4. switch表达式的使用

jdk12、13的预览版如今已成为正式版

switch可以当做语句使用,也可以当作表达式使用。

具体情况:使用->来替代以前的: break;另外还提供了yield来在block中返回值。

最早的switch

public class Test04 {
    public static void main(String[] args) {
        Week day = Week.FRIDAY;
        switch (day){
            case MONDAY:
            case TUESDAY:
            case WEDNESDAY:
                System.out.println(3);
                break;
            case THUSDAY:
                System.out.println(4);
                break;
            case FRIDAY:
                System.out.println(5);
                break;
            case SATURDAY:
                System.out.println(6);
                break;
            case SUNDAY:
                System.out.println(7);
                break;
            default:
                break;
        }
    }
}

enum Week{
    SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THUSDAY,FRIDAY,SATURDAY;
}

JDK12的新特性:引用switch表达式

public static void siwtch12(){
    switch (day) {
        case MONDAY, TUESDAY, WEDNESDAY -> System.out.println(3);
        case THUSDAY -> System.out.println(4);
        case FRIDAY -> System.out.println(5);
        case SATURDAY -> System.out.println(6);
        case SUNDAY -> System.out.println(7);
        default -> System.out.println(1);
    }
}

//还可以用一个参数接收
public static void siwtch12(){
    Week day = Week.FRIDAY;
    int num = switch (day) {
        case MONDAY, TUESDAY, WEDNESDAY -> 3;
        case THUSDAY -> 4;
        case FRIDAY -> 5;
        case SATURDAY -> 6;
        case SUNDAY -> 7;
        default -> 1;
    };

    System.out.println(num);

}

JDK13新特性:引入yield关键字,用于返回指定的数据,结束switch结构,可以理解为return

public void siwtch13(){
        String x = "5";
        int num = switch (x){
            case "1"->1;
            case "2"->2;
            case "3":yield 3;
            default -> {
                System.out.println("default..");
                yield 4;
            }
        };
        System.out.println(num);
    }

5. 文本块(预览版)

jdk14增加了两个转义字符:\禁止换行 \s空格

目标:

  • 简化跨越多行的字符串,避免对换行等特殊子进行转义,简化编写Java程序
  • 增强Java程序中用字符串表示的其他语言的代码的可读性
  • 解析新的转义序列
//jdk13以前
String text1 = "China's football club Guangzhou Evergrande " +
    "and Taobao reported a loss of 1.9 billion yuan (274 million US dollars)" +
    " in 2019, according to the National Equities Exchange " +
    "and Quotations (NEEQ) listed company's annual report " +
    "released on Wednesday.";

System.out.println(text1);

//jdk13新特性(前后3个双引号包裹文本)
String text2 = """
    China's football club Guangzhou Evergrande 
    and Taobao reported a loss of 1.9 billion yuan (274 million US dollars) 
    in 2019, according to the National Equities Exchange
    and Quotations (NEEQ) listed company's annual report
    released on Wednesday.
    """;
//html
@Test
public void HtmlTest(){
    String html1 = "<!DOCTYPE html>\n" +
        "<html lang=\"en\">\n" +
        "<head>\n" +
        "  <meta charset=\"UTF-8\">\n" +
        "  <title>Title</title>\n" +
        "</head>\n" +
        "<body>\n" +
        "hello \n" +
        "</body>\n" +
        "</html>";

    String html2 = """
        <!DOCTYPE html>
        <html lang="en">
        <head>
        <meta charset="UTF-8">
        <title>Title</title>
        </head>
        <body>
        hello\s
        </body>
        </html>
        """;
}

还有一些如JSON、SQL语句都可以这样使用。

JDK14的新特性,\\s

@Test
public void TestJDK14(){
    String html2 = """
        <!DOCTYPE html>\
        <html lang="en">
        <head>
        <meta charset="UTF-8">
        <title>Title</title>
        </head>
        <body>
        hello\sworld
        </body>
        </html>
        """;
        
    System.out.println(html2);
}

//结果
<!DOCTYPE html><html lang="en">  //没有换行
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
hello world  //中间多了空格
</body>
</html>


Process finished with exit code 0

6. 弃用一个垃圾收集器组合

在这里插入图片描述

jdk9废除(Serial+CMS) (ParNew+Serial Old)

jdk14弃用(ParallelScavenge +SerialOld GC)

弃用-XX:+UseParallelGC-XX :- UseParallelOldGC组合,-XX:UseParallelOld GC选项也被弃用,因为它的作用是取消老年代并行GC,支持老年代串行GC。因此,任何与UseUseParallelOldGC选项有关的用法都会输出警告。

7. 删除CMS垃圾回收器

自从G1(基于Region分代)横空出世后,CMS在JDK9就被标记为弃用。

原因:

  • 会产生内存碎片,导致并发清除后,用户线程可用的空间不足
  • 既然强调了并发,CMS收集器对CPU资源非常敏感
  • CMS收集器无法处理浮动垃圾(一个线程清理垃圾,另一个线程产生垃圾)。

两个新的收集器

ZGC(JDK11出现) 和 Shenandoah (open jdk12)

特点:低停顿时间/低延迟

8. ZGC (试验状态)

在尽可能对系统吞吐量影响不大的前提下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在10ms以内的低延迟。

它是一款以低延迟为首要目标的一款垃圾收集器

ps: 还有一些不太常用的新特性,这边就不指出了!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值