当前位置: 首页 > news >正文

Java基础关键_037_Java 常见新特性

目  录

一、新语法

1.JShell

2.try-with-resources 

(1)jdk 7 之前

(2)jdk 7 之后 

(3)jdk 9 之后 

3.局部变量类型判断(不推荐)

4.instanceof 的模式匹配

(1)之前写法

(2)模式匹配增强

5.switch

(1)之前写法 

(2)jdk 12 之后

(3)jdk 13 之后

6.文本块

7.Record

8.密封类 / 接口

二、新 API

1.String

(1)存储结构改变

(2)jdk 11 新增方法

(3)jdk 12 新增方法

2.接口支持私有方法

3.标识符命名变化

4.简化编译运行程序

5.创建只读集合

6.Optional

(1)创建 Optional 对象

(2)Optional 类的方法


一、新语法

1.JShell

        JShell 是 jdk 9 引入的,像 Python、Scala 等语言之前就有交互式编程环境(REPL)。开发者只需要输入一些代码,就可以在编译前获得反馈。之前版本的 Java,必须创建文件、声明类、提供测试方法。


2.try-with-resources 

(1)jdk 7 之前

        在之前的章节我们就知道,所有被打开的资源(流、文件、Socket 连接 等)        都需要手动关闭,否则随程序不断运行,会造成严重的资源泄漏。

        在 jdk 7 之前,需要在 finally 代码块中完成资源的关闭。

public class TryWithResources {
    public static void main(String[] args) {
        // jdk 7 之前,创建资源对象,然后调用 close() 方法关闭资源
        FileReader fileReader = null;
        FileWriter fileWriter = null;
        try {
            fileReader = new FileReader("D:\\apache-maven-3.6.3\\bin\\m2.conf");
            fileWriter = new FileWriter("D:\\m2.conf");
            int readCount = 0;
            char[] chars = new char[1024];
            while ((readCount = fileReader.read()) != -1) {
                fileWriter.write(chars, 0, readCount);
            }
            fileWriter.flush();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                }
                if (fileWriter != null) {
                    fileWriter.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

(2)jdk 7 之后 

        jdk 7 之后,应该使用 try-with-resources 语法自动关闭资源。

        使用该语法,需要关闭资源的对象的对应类应该实现 java.lang.AutoCloseable 接口,该接口提供了一个抽象的 close 方法。

public class TryWithResources {
    public static void main(String[] args) {
        // jdk 7 之后,可以使用try-with-resources语句,自动关闭资源
        try (FileReader reader = new FileReader("D:\\apache-maven-3.6.3\\bin\\m2.conf");
             FileWriter writer = new FileWriter("D:\\m2.conf")) {
            int readCount = 0;
            char[] chars = new char[1024];
            while ((readCount = reader.read()) != -1) {
                writer.write(chars, 0, readCount);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(3)jdk 9 之后 

        jdk 9 之后,再次进行改进。

public class TryWithResources {
    public static void main(String[] args) throws Exception {
        // jdk 9 之后,try-with-resources 再次改进
        FileReader reader = new FileReader("D:\\apache-maven-3.6.3\\bin\\m2.conf");
        FileWriter writer = new FileWriter("D:\\m2.conf");
        try (reader; writer) {
            int readCount = 0;
            char[] chars = new char[1024];
            while ((readCount = reader.read()) != -1) {
                writer.write(chars, 0, readCount);
            }
            writer.flush();
        }
    }
}

3.局部变量类型判断(不推荐)

        jdk 10 之后,新增了局部变量类型判断。在方法体或代码块当中,对于可以在编译期确定的类型,可以使用 var 来定义。对于编译期无法确定的类型,仍需写清楚类型。但是不推荐使用。

public class VarType {
    public static void main(String[] args) {
        /*int i = 1;
        double d = 1.0;
        String s = "hello";
        boolean b = true;*/
        var i = 1;
        var d = 1.0;
        var s = "hello";
        var b = true;
        System.out.println(i);
        System.out.println(d);
        System.out.println(s);
        System.out.println(b);
    }
}


4.instanceof 的模式匹配

        jdk 14 新增预览,jdk 16 正式版。通过 instanceof 模式匹配增强,可以直接在模式匹配的括号中声明对应类型的局部变量。 

(1)之前写法

public class Person {
}
public class Student extends Person {
    public void study() {
        System.out.println("study");
    }
}
public class InstanceofTest {
    public static void main(String[] args) {
        Person p = new Student();
        if (p instanceof Student) {
            Student student = (Student) p;
            student.study();
        }
    }
}

(2)模式匹配增强

public class InstanceofTest {
    public static void main(String[] args) {
        Person p = new Student();
        if (p instanceof Student s) {
            s.study();
        }
    }
}

5.switch

  1. 之前 switch 表达式:
    1. 匹配自上而下,没有 break,则后边的 case 语句都会被执行;
    2. 不同 case 定义的变量名不能相同;
    3. 不允许在一个 case 后边写多个值;
    4. 整个 switch 不可以作为表达式的返回值。
  2. jdk 12 之后的 switch 表达式更加简洁。

(1)之前写法 

public class SwitchTest {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("欢迎查询季节");
        System.out.print("请输入月份:");
        int month = in.nextInt();
        switch (month) {
            case 3:
            case 4:
            case 5:
                System.out.println("春季");
                break;
            case 6:
            case 7:
            case 8:
                System.out.println("夏季");
                break;
            case 9:
            case 10:
            case 11:
                System.out.println("秋季");
                break;
            case 12:
            case 1:
            case 2:
                System.out.println("冬季");
        }
    }
}

(2)jdk 12 之后

public class SwitchTest {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("欢迎查询季节");
        System.out.print("请输入月份:");
        int month = in.nextInt();
        String season = switch (month) {
            case 3, 4, 5 -> "春季";
            case 6, 7, 8 -> "夏季";
            case 9, 10, 11 -> "秋季";
            case 12, 1, 2 -> "冬季";
            default -> "输入有误!";
        };
        System.out.println(season);
    }
}

(3)jdk 13 之后

public class SwitchTest {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("欢迎查询季节");
        System.out.print("请输入月份:");
        int month = in.nextInt();
        String season = switch (month) {
            case 3:
            case 4:
            case 5:
                yield ("春季");
            case 6:
            case 7:
            case 8:
                yield ("夏季");
            case 9:
            case 10:
            case 11:
                yield ("秋季");
            case 12:
            case 1:
            case 2:
                yield ("冬季");
            default:
                yield ("输入有误!");
        };
        System.out.println(season);
    }
}

6.文本块

        Java 中,通常使用 String 类型表达 HTML、XML、SQL、JSON 等格式的字符串,在进行字符串赋值时,需要进行转义和连接操作,然后才能编译该代码,这种方式难以阅读和维护。

        jdk 12 新增文本块,文本块就是多行字符串,有了文本块以后,用户无需转义,由 Java 自动完成。

public class TextBlock {
    public static void main(String[] args) {
        String text = """
                <html>
                	<head>
                		<title>Test</title>
                	</head>
                	<body>
                		<p>This is test program.<p>
                	</body>
                </html>           
                """;
        System.out.println(text);
    }
}

7.Record

        在开发中,需要一个类只做纯数据载体、不负责修改等操作,可以将这种类型定义为 Record 类型。可以省略 构造方法、get / set 方法,toString 方法、equals 方法、 hashCode 方法 等等。

        Record 类型可以添加:无参构造方法、静态变量、静态方法、实例方法。

public record Animal(String name, int age) {
    // 自动生成构造方法,getter方法,toString方法,equals方法,hashCode方法,还有两个被 final 修饰的实例变量

    // 添加无参构造方法
    public Animal {
        System.out.println("Animal()");
    }

    // 添加静态变量
    public static final String TYPE = "Animal";

    // 添加静态方法
    public static void eat() {
        System.out.println("Animal.eat()");
    }

    // 添加实例方法
    public void run() {
        System.out.println("Animal.run()");
    }
}
public class RecordTest {
    public static void main(String[] args) {
        Animal animal = new Animal("Dog", 4);
        System.out.println(animal.name());
        System.out.println(animal.age());
        System.out.println(animal);
        System.out.println(Animal.TYPE);
        Animal.eat();
        animal.run();
    }
}


8.密封类 / 接口

  1. 一种新的类修饰符,可以修饰类和接口可以控制哪些类可以扩展或实现该类或接口;
  2. 作用:
    1. 维护类层次结构的密闭性:可以保证一组类不被其他类继承或实现,确保了代码的安全性和稳定性;
    2. 预防代码意外扩展:可以保证在特定的类中才能继承或实现指定的类,强制限制可以继承或实现类的范围;
    3. 增强可读性和可维护性。
  3. jdk 15 新增,使用 sealed关键字修饰的类就是密封类;
  4. 密封类必须是父类或接口,可以使用 permits 关键字指定哪些子类可以继承该密封类或实现该密封接口
  5. 密封类的子类必须使用 sealed、final、non-sealed 来修饰;
  6. Record 类型默认被 final 修饰,其可以做密封接口的实现类
public sealed class Person permits Student, Teacher{
}
public final class Student extends Person {
}
public non-sealed class Teacher extends Person {
}

二、新 API

1.String

(1)存储结构改变

        jdk 9 之前,String 底层采用 char 类型数组存储字符。

        从 jdk 9 开始,String 底层采用 byte 数组,目的是为了节省空间。


(2)jdk 11 新增方法

public class StringNewMethod {
    public static void main(String[] args) {
        /*
         * isBlank(),空格、制表符、换行都认为是空
         * */
        String s1 = " ", s2 = "\t", s3 = "\n";
        System.out.println(s1.isBlank() + " " + s2.isBlank() + " " + s3.isBlank()); // true true true

        /*
         * repeat(),重复字符串 n 次
         * */
        String s4 = "I Love You! ";
        System.out.println(s4.repeat(3));   // I Love You! I Love You! I Love You!

        /*
         * strip(),去除字符串首尾空格
         * */
        String s5 = "  I Miss You!\t";
        System.out.println(s5.strip()); // I Miss You!

        /*
         * stripLeading(),去除字符串首空格
         * */
        String s6 = "  I Hate You!\t";
        System.out.println(s6.stripLeading());  // I Hate You!

        /*
         * stripTrailing(),去除字符串尾空格
         * */
        String s7 = "  I Forgot You!\t";
        System.out.println(s7.stripTrailing()); //   I Forgot You!

        /*
         * lines(),将字符串按行分割,返回一个 Stream
         * */
        String s8 = "I\nAm\nReborn!";
        s8.lines().forEach(System.out::println);
        // I
        // am
        // reborn!
    }
}


(3)jdk 12 新增方法

public class StringNewMethod {
    public static void main(String[] args) {
        /*
         * indent(),缩进 n 个字符串
         * */
        String s9 = "I Like Her!";
        System.out.println(s9.indent(6));
    }
}


2.接口支持私有方法

        jdk 8 中,接口支持公开静态方法和公开默认方法。

        jdk 9 中,接口允许定义私有静态方法和私有成员方法,但不能定义私有默认方法。 

public interface InterfaceTest {
    public static void staticMethods(){

    }

    public default void defaultMethods(){

    }

    public void methods();

    private static void privateStaticMethods(){

    }

    private void privateMethods(){

    }
}

3.标识符命名变化

        jdk 9 之前,标识符可以独立使用【_】命名。

        jdk 9 开始,不能用下划线独立命名标识符了。


4.简化编译运行程序

        运行一个 java 文件,必须先编译(javac),再运行(java)。

        但是 jdk 11 开始,只需要一个 java 命令即可。


5.创建只读集合

        jdk 9 开始,可以通过 List、Set、Map 接口提供的 of(E… elements) 静态方法创建不可变集合。

public class NotChangeCollection {
    public static void main(String[] args) {
        List<Integer> list = List.of(1, 2, 3);
        list.forEach(System.out::println);
        // 不可以增、删、改
        // list.add(4);
        // list.remove(0);
        // list.set(0, 4);

        Set<Double> set = Set.of(3.14, 5.20, 13.14);
        set.forEach(System.out::println);
        // 不可以增、删、改
        // set.add(4.14);
        // set.remove(0);
        // set.set(0, 4.14);

        Map<Integer, String> map = Map.of(1, "I ", 2, "Love ", 3, "You");
        map.forEach((k, v) -> System.out.println(k + ":" + v));
        // 不可以增、删、改
        // map.put(4, "!");
        // map.remove(1);
        // map.replace(2, "!");

        List<String> stringList = Arrays.asList("Hello", "World");
        stringList.forEach(System.out::println);
        // 不可以增、删
        // stringList.add("!");
        // stringList.remove(0);
        // 可以修改
        stringList.set(0, "qqq");
        stringList.forEach(System.out::println);
    }
}


6.Optional

        jdk 8 之前,为了避免错误引用 null 造成空指针异常,经常需要一系列复杂的判空操作。

        jdk 8 开始,引入了 Optional 类,可以简单的对 null 值处理,从而避免空指针异常。Optional 类是一个包含有可选项的包装类,意味着 Optional 类中既可以含有对象也可以为 null。 

(1)创建 Optional 对象

        使用 Optional 类提供的 of() 和 ofNullable() 静态方法创建包含值的 Optional 实例。

        若将 null  当作参数传入 of() ,会抛空指针异常。若将 null 当参数传入 ofNullable() ,不会抛出空指针异常。

        因此,当对象可能存在或不存在,应使用 ofNullable() 创建Optional 实例。


(2)Optional 类的方法

  1. T get():若值不为 null 则直接取出该值,若为 null 则抛出空指针异常;
  2. T orElse(T other):若值不为 null 则直接取出该值,若为 null 则取出参数 other 的值。

相关文章:

  • 深度解析Redis过期字段清理机制:从源码到集群化实践 (二)
  • OSPF单区域配置实验
  • 软件测试之单元测试详解
  • [LVGL] 使用lvgl自带的链表函数
  • CSV文件中的中文乱码--UTF-8 with BOM
  • DeepSeek 与开源:肥沃土壤孕育 AI 硕果
  • react/vue中前端多图片展示页面优化图片加载速度的五种方案
  • 高德地图 JS-SDK 实现教程
  • LFM调制信号分类与检测识别
  • electron-builder参数详解
  • 医用多功能压力检测仪,精密医疗的守护者
  • 04 GE - 钳制属性,等级
  • 面向MoE和推理模型时代:阿里云大数据AI产品升级发布
  • k8s中缩放pod规格
  • 微信小程序-下拉滚动加载数据
  • (2025亲测可用)Chatbox多端一键配置Claude/GPT/DeepSeek-网页端配置
  • XDocument和XmlDocument的区别及用法
  • Java 正则表达式综合实战:URL 匹配与源码解析
  • 详细解读TypeScript中 declare 关键字
  • 2k1000LA , 调试串口改成通信串口, uart.
  • 公元1058年:柳永词为什么时好时坏?
  • 浙能集团原董事长童亚辉被查,还是杭州市书法家协会主席
  • 宝通科技:与宇树合作已签约,四足机器人在工业场景落地是重点商业化项目
  • 郑培凯:汤显祖的“至情”与罗汝芳的“赤子之心”
  • 牛市早报|中美日内瓦经贸会谈联合声明公布
  • 80后莆田市文旅局长马骏登台与杨宗纬合唱,“演唱会秒变旅游推介会”