JDK8-17新特性-JDK8之后的语法新特性汇总下

一、switch表达式

  • 1.传统switch声明语句的弊端:

    • 匹配是自上而下的,如果忘记写break,后面的case语句不论匹配与否都会执行; ---> case 穿透
    • 所有的case语句共有一个块范围,在不同的case语句定义的变量名不能重复;
    • 不能在一个case里写多个执行结果一致的条件;
    • 整个switch不能作为表达式返回值;

二、JDK12中预览特性

  • java 12 将会对switch 声明语句进行扩展,使用case L -> 来代替以前的break;,省去了break语句,笔迷拿了因少写break而出错。

  • 同时将多个case合并到一行,显得简洁、清晰,也更加优雅的表达逻辑分支。

  • 为了保持兼容性,case条件语句中依然可以使用字符:,但是同一个 switch 结构里不能混用 -> 和 : ,否则编译错误。

  • JDK12中的写法:switch表达式,省去了break语句,避免了因少些break而出现case穿透
/**
 * 示例一
 * JDK12中的写法:switch表达式,省去了break语句,避免了因少些break而出现case穿透
 */
@Test
void test2() {
    Week day = Week.FRIDAY;
    switch (day){
        case MONDAY -> System.out.println(1);
        case TUESDAY,WEDENSDAY,THURSDAY -> System.out.println(2);
        case FRIDAY -> System.out.println(3);
        case SATURDAY,SUNDAY -> System.out.println(4);
        default ->
            throw new RuntimeException("??????????" + day);
    }
}
  • JDK12中的写法: 还可以使用变量接收switch表达式的结果
/**
 * 示例一
 * JDK12中的写法: 还可以使用变量接收switch表达式的结果
 */
@Test
void test2() {
    Week day = Week.FRIDAY;
    int result = switch (day){
        case MONDAY -> 1;
        case TUESDAY,WEDENSDAY,THURSDAY -> 2;
        case FRIDAY -> 3;
        case SATURDAY,SUNDAY -> 4;
        default ->
            throw new RuntimeException("??????????" + day);
    };
    System.out.println(result);
}
  • JDK13中的写法: 引入了yield关键字,用于返回指定的数据,结束switch结构
  • 这意味着,switch表达式(返回值)应该使用yield,switch语句(不返回值)应该使用break。
  • 和return的区别在于:return会直接跳出当前方法,而yield只会跳出当前switch块
    • 写法一:
/**
 * 示例一
 * JDK13中的写法: 引入了yield关键字,用于返回指定的数据,结束switch结构
 * 这意味着,switch表达式(返回值)应该使用yield,switch语句(不返回值)应该使用break。
 * 和return的区别在于:return会直接跳出当前方法,而yield只会跳出当前switch块
 */
@Test
void test3() {
    Week day = Week.FRIDAY;
    int result = switch (day){
        case MONDAY -> { yield 1;}
        case TUESDAY,WEDENSDAY,THURSDAY -> { yield 2;}
        case FRIDAY -> { yield 3;}
        case SATURDAY,SUNDAY -> { yield 4;}
        default ->
        {
            System.out.println("?????????????");
            yield 5;
        }
    };
    System.out.println(result);
}
  • 写法二:
@Test
void test3() {
    Week day = Week.FRIDAY;
    int result = switch (day){
        case MONDAY : yield 1;
        case TUESDAY,WEDENSDAY,THURSDAY : yield 2;
        case FRIDAY : yield 3;
        case SATURDAY,SUNDAY :yield 4;
        default :
            System.out.println("?????????????");
            yield 5;
    };
    System.out.println(result);
}

3.JDK17的预览特性:switch的模式匹配

/*
 * JDK17中的switch的模式匹配
 */
@Test
static String formatterSwitchPattern(Object o) {
​
    String formatted = switch (o) {
        case Integer i:
            yield "int " + i;
        case Long l:
            yield "long " + l;
        case Double d:
            yield "Double " + d;
        default:
            yield o.toString();
    };
​
    return formatted;
}

4.文本块的使用

  • 对比1-html格式

  • 使用文本块:

  • 对比2-JSON格式

  • 使用文本块:

  • 对比3-SQL格式

  • 使用文本块:

  • JDK14新特性:
    • \:取消换行操作
    • \s:表示一个空格
/*
 * JDK14新特性
 *  \:取消换行操作
 *  \s:表示一个空格
 */
@Test
void test7() {
    String newQuery1 = """
                SELECT id,name,email \
                From cusomers\s\
                WHERE id > 4 \
                ORDER BY email DESC
            """;
}

5.Record(引用数据类型)的使用

  • record是一种全新的类型,它本质上是一个final类,同时所有的属性都是final修饰,它会自动编译出public get、hashcode、equals、toString、构造器等结构,减少了代码的编写量。

  • 具体来说:当你用record声明一个类时,该类将自动拥有以下功能:

    • 获取成员变量的简单方法,比如例题中的name()和partner()。注意区别于我们平常getter()的写法。
    • 一个equals方法的实现,执行比较时会比较该类的所有成员属性
    • 重写hashCode()方法
    • 一个可以打印该类所有成员属性的toString()方法
    • 只有一个构造方法

  • 演示:
public record Order1(int orderId,String orderName) {
    
}

public class Order {
​
    private final int orderId;
    private final String orderName;
​
    public Order(int orderId, String orderName) {
        this.orderId = orderId;
        this.orderName = orderName;
    }
​
    public int getOrderId() {
        return orderId;
    }
​
    public String getOrderName() {
        return orderName;
    }
​
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Order order = (Order) o;
        return orderId == order.orderId && Objects.equals(orderName, order.orderName);
    }
​
    @Override
    public int hashCode() {
        return Objects.hash(orderId, orderName);
    }
​
    @Override
    public String toString() {
        return "Order{" +
                "orderId=" + orderId +
                ", orderName='" + orderName + '\'' +
                '}';
    }
}
  • 测试

/*
 * 测试-order
 */
@Test
void test8() {
    Order order1 = new Order(1001, "orderAA");
    //测试toString()
    System.out.println(order1);
​
    //测试getter()
    System.out.println(order1.getOrderId());
    System.out.println(order1.getOrderName());
​
    Order order2 = new Order(1001, "我是你爸爸");
    //测试equals()
    System.out.println(order1.equals(order2));
​
    //测试hashCode()和equals()
    HashSet<Order> set = new HashSet<>();
    set.add(order1);
    set.add(order2);
    System.out.println(set);
}
​
/*
 * 测试-order1
 */
@Test
void test9() {
    Order1 order1 = new Order1(1001, "orderAA");
    //测试toString()
    System.out.println(order1);
​
    //测试getter()
    System.out.println(order1.orderId());
    System.out.println(order1.orderName());
​
    Order1 order2 = new Order1(1001, "我是你爸爸");
    //测试equals()
    System.out.println(order1.equals(order2));
​
    //测试hashCode()和equals()
    HashSet<Order1> set = new HashSet<>();
    set.add(order1);
    set.add(order2);
    System.out.println(set);
}

此外:

  • 还可以在record声明的类中定义静态字段、静态方法、构造器或实例方法。
  • 不能在record中声明的类中定义实例字段;类不能声明为abstract;不能声明显示的父类等。

注意:record的设计目标是提供一种将数据建模为数据的好方法。它也不是 JavaBeans 的直接替代品,应为 record 的方法不符合 JavaBeans 的get 标准。另外 JavaBeans 通常是可变的,而记录是不可变的。尽管他们的用途有点像,但记录并不会以某种方式取代 JavaBean。

  • 示例:

public record Person(int id,String name) {
​
    //- 还可以在 record 声明的类中定义静态字段、静态方法、构造器或实例方法。
    static String info = "我是你爸爸";
​
    public static void show(){
        System.out.println("我真的你是爸爸!!!");
    }
​
    public Person(){
        this(0,null);
    }
​
    public void eat(){
        System.out.println("其实我不是你爸爸,我是你爷爷~~~没想到吧");
    }
​
    //- 不能再record声明的类中定义实例字段;类不能声明为abstract;不能声明显示的父类等。
    //final int age;
​
    //abstract record Dog(int id){}
    //record Cat(int id) extends Thread{}
    //class Student extends Person{}
​
}

6.密封类

  • 背景:

在Java中如果想让一个类不能被继承和修改,则会使我们应该使用final关键字对类进行修饰。不过这种要么可以继承,要么不能继承的机制不够灵活,有些时候我们可能想让某个类可以被某些类型继承,但是又不能随意继承,是做不到的。Java15尝试解决这个问题,引入了 sealed 类,被sealed 修饰的类可以指定子类。这样这个类就只能被指定的类继承。

  • JDK15的预览特性

通过秘方的类和接口来限制超类的使用,密封的类和接口限制其它可能继承或实现他们的其它类或接口

具体使用:

  • 使用修饰符 sealed,可以将一个类声明为密封类。密封的类使用保留关键字 permits累出可以直接扩展(即extends)它的类。
  • sealed 修饰的类的机制具有传递性,他的子类必须使用指定的关键字进行修饰,且只能是final、sealed、non-sealed三者之一。

7.API的变化

Optional类

  • JDK8新特性
Optional<T>类(java.util.Optional)是一个容器类,他可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。如果值存在,则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional提供很多有用的方法,这样我们就不用显示进行空值检测。

JDK8的新特性,JDK9-11中新增了一些方法。

  • 1.为什么需要Optional类?
    为了避免代码中出现空指针异常。

  • 2.如何实例化?
static<T>Optional<T> ofNullable(T value): 用来创建一个Optional实例,value可能是空,也可能是非空。

  • 3.常用方法
    • 创建Optional类对象的方法:
      • static<T> Optional<T> empty():用来创建一个空的Optional实例
      • static<T> Optional<T> of(T value):用来创建一个Optional实例,value必须非空
      • static <T> Optional<T> ofNullable(T value):用来创建一个Optional实例,value可能是空,也可能非空
    • 判断Optional容器中包含对象:
      • boolean isPresent():判断Optional容器中的值是否存在
      • void ifPresent(Consumer<? super T> consumer): 判断Optional容器中的值是否存在,如果存在,就对他进行Consumer指定的操作,如果不存在就不做
    • 获取Optional容器的对象:
      • T get(): 如果调用对象包含值,返回该值。否则抛异常。T get()与of(T value)配合使用
      • T orElse(T other):orElse(T other)与ofNullable(T value)配合使用,如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other)other指定的默认值(备胎)代替
      • T orElseGet(Supplier<? extends T> other):如果Optional容器中非空,就返回所包装值,如果为空就用Supplier接口的Lambda表达式提供的值代替
      • T orElseThrow(Supplier<? extends T> exceptionSupplier):如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException
  • 代码示例:
@Test
void test01() {
    String star = "你爸爸";
​
    //使用Optional避免空指针的问题
    //1.实例化:
    //ofNullable(T value):用来创建一个Optional实例,value可能是空,也可能非空
    Optional<String> optional = Optional.ofNullable(star);
​
    //orElse(T other):如果Optional实力内部的value属性不为null,
    // 则返回value,如果value为null,则返回other。
    String otherStar = "你爷爷";
    String finalStar = optional.orElse(otherStar);
​
    System.out.println(finalStar.toString());
​
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值