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

jdk9 -> jdk17 编程方面的变化

文章目录

    • Java各个版本的主要特性
    • Java 9 模块化
      • 简单使用
      • module-info.java 标签讲解
      • JAVA 9 更严格的反射限制
      • 单元测试模块化设置
    • Jave 9 JShell
    • Java 9 接口中的私有方法
    • Java 9 集合类新增工厂方法
    • Java 9 改进的Stream API
      • ofNullable
      • iterate 方法重载
      • takeWhile dropWhile
    • Java 9 其他改进的API
    • Java 10 局部变量类型推断
    • Java 11 Lambda形参局部类型推断
    • Java 11 字符串处理方法
    • Java12 switch改进
    • Java13 文本块 提升编写效率
    • JAVA14 空指针异常的改进
    • JAVA16 instance 新特性
    • JAVA 16 记录类型
    • Java 17 密封类
    • 学习地址

java LTS 版本包括Java 8、Java 11、Java 17、Java 21和Java 24.

这个文档 仅仅讲述 jdk9 -> jdk17 编程方面的变化.

java 升级方向:语法方向: 模块化 var类型 Switch扩展 文本语法API方向: 字符串处理 Stream API   HTTP Client重构 性能方向: GC垃圾回收器增强 JFR性能分析记录 关注语法和API两个方向的升级. 

Java各个版本的主要特性

●Java 9:模块化、默认G1 回收、jShell(类似 Ruby 的 console)

Java10:G1的并行完全垃圾回收、var类型、类数据共享、Thread-Local Handshakes

Java 11:TLS1.3、HTTP Client重构、ZGC 垃圾回收、可运行源文件、JFR(性能分析记录)

●Java 12:扩展Switch、支持Unicode11、字符串的transform、indent

Java 13:增强 ZGC 垃圾回收、SocketAPI重构

Java 14:Record类型(可代替lombok)-预览、删除CMS垃圾回收器

Java 15:支持 EdDSA 加密、文本块语法、Hidden Classes

Java 16:instanceof模式匹配、Record类型、ZGC并发处理支持

Java17:密封类、增强的伪随机数生成器

Java 9 模块化

出现的原因: 即使仅仅需要jar中其中很少的一部分类, 也需要将整个jar包完全导入. 增加了包的体积, 降低了加载效率.

模块化: 在package的上一层创建module, module管理一个或若干个package. 使用module作为导入单位.

JDK17 默认导入的模块
在这里插入图片描述

自动导入模块分这么几种情况:

  1. java.base 自动导入
  2. java8 之前写的包, 自动导入.
  3. 未命名模块, 没有写module-info.java的, 自动导入.

简单使用

注意:当出现创建的模块, 不能创建module-info.java类似问题后,请检查 module language level.
在这里插入图片描述
项目结构如图所示:
在这里插入图片描述
新建untitled 模块, 创建Main.java module-info.java.

module-info.java

module untitled {requires java.sql;  //导入java.sql模块
}

Main.java

package com.songlili.test;
import java.sql.Connection;/*** @author guchu* @since 2025/7/20  11:43* description*/
public class Main {public static void main(String[] args) {System.out.println("Hello World!");Connection connection = null;}
}

情况如下:

  1. 没有moudle-info.java, 自动导入java.sql模块
  2. 添加module-info.java, 必须明确导入 java.sql模块.否则报错.

module-info.java 标签讲解

java.sql模块的module-info.java如下:

module java.sql{require transitive java.logging; require transitive java.transaction.xa;require transitive java.xml;export java.sql;export javax.sql;uses java.sql.Driver;   
}

require java.logging; //声明需要导入的模块

require transitive java.logging; //声明需要java.logging模块并且递归导入. moduleA 导入了java.sql, moduleB 导入了moduleA, moduleB会自动导入java.logging模块. 否则需要再次导入

export java.sql; //导出java.sql 包

uses java.sql.Driver; // uses 用于声明当前模块 使用 某个服务接口(Service Interface),表明该模块可能会通过 ServiceLoader 动态加载该服务的实现类。

module eeg.com.taman{
exports taman.service;  //向所有引入该模块的模块,导出taman.service;
exports ...to ...;   //向谁导出 eg. exports taman.service.abc to moduleA 只有moduleA可以使用 taman.service.abc
provide ...with ...; // 声明 对外提供的服务
requires java.sql;
opens java.logging;  //完全开放 java.logging的反射访问.
opens java.logging to moduleA; //对moduleA 开放 java.logging的反射访问.
}

require moduleA; //各个阶段均可用

require static moduleA; //编译使用, 运行阶段不行.

创建模块基本原则

每个模块都有一个唯一的名称
因为模块存在于JVM的全局空间中,所以每个模块都应该有一个唯一的名称。与包和JAR文件名
一样,您可以使用反向域名模式来定义模块名称。
每个模块在源文件中都有一些描述
模块描述在一个名为module-info.java的源文件中表示,并且应该完全像这样命名。每个模块
应该有一个且只有一个模块描述符(module-info.java)。模块描述符是一个Java文件。它不
是XML、文本或属性文件。
模块描述符文件放在顶层目录
顶层目录是模块的根文件夹。
每个模块可以有任意数量的包和类型
一个模块可以依赖于任意数量的模块

JAVA 9 更严格的反射限制

 private void reflectionCall(){Class<User> clazz = User.class;try {User user = clazz.newInstance();Field nameField = clazz.getDeclaredField("name");nameField.setAccessible(true);Object o = nameField.get(user);System.out.println(o);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (NoSuchFieldException e) {throw new RuntimeException(e);}}

即使添加 nameField.setAccessible(true);也不能访问私有方法. 权限管理更强了,真正做到了私有.
User所在的模块, 对当前模块打开反射权限,才能够进行反射访问.

module APIModule {exports com.songlili.api;opens com.songlili.api to  untitled;  //支持反射访问opens com.songlili.api ; //对所有的模块开放反射访问
}

单元测试模块化设置

除了导入junit之外, 还要将自身暴露给junit.

package com.songlili.abc;/*** @author guchu* @since 2025/7/20  14:50* description*/
public class Test {@org.junit.Testpublic void test() {System.out.println("hello world");}
}
D:\Java\jdk-17.0.15\bin\java.exe -javaagent:D:\Jetbrain\ideaIU-2025.1.3\plugins\java\lib\rt\debugger-agent.jar=file:///C:/Users/guchu/AppData/Local/Temp/capture4154079601837761278.props -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:D:\Jetbrain\ideaIU-2025.1.3\lib\idea_rt.jar=64214 -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true --add-modules ModuleTest2 -Dfile.encoding=UTF-8 -classpath D:\Jetbrain\ideaIU-2025.1.3\lib\idea_rt.jar;D:\Jetbrain\ideaIU-2025.1.3\plugins\junit\lib\junit5-rt.jar;D:\Jetbrain\ideaIU-2025.1.3\plugins\junit\lib\junit-rt.jar;C:\Users\guchu\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar -p E:\JdkNewFeature\ModuleTest2\target\test-classes;C:\Users\guchu\.m2\repository\junit\junit\4.12\junit-4.12.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.songlili.abc.Test,testjava.lang.IllegalAccessException: class org.junit.runners.BlockJUnit4ClassRunner (in module junit) cannot access class com.songlili.abc.Test (in module ModuleTest2) because module ModuleTest2 does not export com.songlili.abc to module junitat java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:489)at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)at junit@4.12/org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)at junit@4.12/org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)at junit@4.12/org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at junit@4.12/org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)at junit@4.12/org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)at junit@4.12/org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)at junit@4.12/org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)at junit@4.12/org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)at junit@4.12/org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at junit@4.12/org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)at junit@4.12/org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)at junit@4.12/org.junit.runners.ParentRunner.run(ParentRunner.java:363)at junit@4.12/org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:231)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)进程已结束,退出代码为 -1

日志说的是, junit 无法访问 当前Main, 需要将当前包进行导出.

module ModuleTest2 {requires junit;exports com.songlili.abc; //导出当前包.
}

Jave 9 JShell

JShell 交互式工具. python自带的命令行工具、浏览器控制台. 直接输入命令, 查看结果. 进行交互.

Java 9 接口中的私有方法

java8 允许接口定义有默认实现和静态方法.
java9 支持接口定义私有方法.

package com.songlili.abc;/*** @author guchu* @since 2025/7/20  14:59* description*/
public interface MyInterface {void test();default void test2() {System.out.println("test2");}static void test3() {System.out.println("test3");}private void test4() {System.out.println("test4");}}

Java 9 集合类新增工厂方法

Map List Set 支持of方法快速创建.

package com.songlili.abc;import java.util.HashMap;
import java.util.Map;/*** @author guchu* @since 2025/7/20  15:16* description*/
public class CollectionFactoryMethod {public static void main(String[] args) {Map<Object,Object> map = new HashMap<>();map.put("name","songlili");map.put("age",18);System.out.println(map);//支持连写, 快捷添加元素.Map<String, Object> name = Map.of("name", "songlili", "age", 18);System.out.println( name);}
}

Java 9 改进的Stream API

ofNullable

public class StreamAPI {public static void main(String[] args) {Stream.ofNullable(null).distinct().filter(s -> s.equals("B")).forEach(System.out::println);}
}

iterate 方法重载

支持退出条件

      Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);

从java 9 开始, 支持退出机制.

      Stream.iterate(0,  n->n < 20, n -> n + 2).forEach(System.out::println);

takeWhile dropWhile

        Stream.iterate(0, n -> n + 2).limit(10).takeWhile(n -> n %2 == 0) //取偶数.forEach(System.out::println);Stream.iterate(0, n -> n + 2).limit(10).dropWhile(n -> n %2 != 0) //丢掉奇数.forEach(System.out::println);

Java 9 其他改进的API

  1. 资源自动释放 变量定义位置更灵活

java7 语法 try with 释放资源写法.

        try(FileOutputStream fos = new FileOutputStream("D:\\test.txt");FileOutputStream fos2 = new FileOutputStream("D:\\test.txt");){}catch (Exception e){e.printStackTrace();}

java9 提升
只需要将要释放资源的变量 放到try即可. 多个使用;进行分割

    public static void main(String[] args) throws  Exception{FileOutputStream fos = new FileOutputStream("D:\\test.txt");FileOutputStream fos2 = new FileOutputStream("D:\\test.txt");try(fos;fos2){}catch (Exception e){e.printStackTrace();}}
  1. Optional.ifPresentOrElse 判定为空, 自定义处理逻辑.
    Optional.ofNullable.or 支持null分支处理.
//java8  Optional.ofNullable 自动判空, 立即返回. Optional.ofNullable( null).ifPresent(System.out::println);Optional.ofNullable( null).ifPresentOrElse(s -> System.out.println(s),()-> System.out.println("null"));Optional.ofNullable( null).or(() -> Optional.of("B"))  //如果为null,则执行这里. .ifPresent(System.out::println);
  1. Java9 开始 , 匿名内部类使用钻石运算符进行自动类型推断.
public abstract class TestA<T> {public  T t;public TestA(T t){this.t = t;}public abstract T test();
}TestA<String> test = new TestA<>("123"){@Overridepublic String test() {return null;}
};

Java 10 局部变量类型推断

java10 之前 必须明确定义变量类型.

var a= 10; 

自动类型推断, 编译成class文件 也是确切的Integer类型.

Java 11 Lambda形参局部类型推断

Consumer<String> c = (String str) -> {System.out.println(str);
};//Java 11, 可以定义var, 让系统进行类型推断. Consumer<String> c = (var str) -> {System.out.println(str);};

Java 11 字符串处理方法

将字符串按行截取, 得到多个字符串, 自动添加到Stream中.

        String abc = "abc\n123\n456";abc.lines().forEach(System.out::println);

repeat 方法

        String abc = "123";String repeat = abc.repeat(20);System.out.println(repeat);

空格去除.

      String abc = "   abc   ";//java 11 之前System.out.println(abc.trim());//java11 去除两端System.out.println(abc.strip());//java11 去除前面的空格System.out.println(abc.stripLeading());//java11 去除后面的空格System.out.println(abc.stripTrailing());

Java12 switch改进

//java 12 level public static String getLevel(int score){return switch (score/10){case 10,9 -> {//这里可以写System.out.println("score"+score);//Java 14 引入 yieldyield "A";}case 8,7 -> "B";case 6 -> "C";default -> "D";};}

Java13 文本块 提升编写效率

       String htmlStr = """<html><body><div>Hello World</div></body></html>""";System.out.println(htmlStr);

实现原样打印.

<html>
<body>
<div>Hello World</div>
</body>
</html>

JAVA14 空指针异常的改进

可以精确到哪一个变量为null.

    public static int getStrLenSum(String a , String b){return a.length() + b.length();}public static void main(String[] args) {int totalLen = getStrLenSum(null,"world");}
D:\Java\jdk-17.0.15\bin\java.exe -javaagent:D:\Jetbrain\ideaIU-2025.1.3\lib\idea_rt.jar=53267 -Dfile.encoding=UTF-8 -classpath C:\Users\guchu\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar -p C:\Users\guchu\.m2\repository\junit\junit\4.12\junit-4.12.jar;E:\JdkNewFeature\ModuleTest2\target\test-classes -m ModuleTest2/com.songlili.abc.Java11Demo
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "a" is nullat ModuleTest2/com.songlili.abc.Java11Demo.getStrLenSum(Java11Demo.java:13)at ModuleTest2/com.songlili.abc.Java11Demo.main(Java11Demo.java:16)进程已结束,退出代码为 1

JAVA16 instance 新特性

    @Overridepublic boolean equals(Object obj) {if(obj instanceof User user){return name.equals(user.name) && age == user.age;}return false;}

判定 obj 为User对象, 自动进行类型转换 并赋值给user

JAVA 16 记录类型

public  record Account(String username, String password) {}

record 与 kotlin data 很像, 参数必须同时存在 比较是否相同. 根据数值进行比较.

Java 17 密封类

sealed 是 Java 15 引入的预览特性,并在 Java 17 中成为正式特性,它用于限制哪些类可以继承或实现某个类/接口。sealed 关键字的主要用途是提供更精确的继承控制,增强代码的安全性和可维护性。

public sealed class A  permits B{   //允许B继承
}
public final class B extends A{
}

注意事项

子类必须是 final、sealed 或 non-sealed 之一permits 列表中的类必须能够访问密封类子类必须与密封类在同一模块中(或未命名模块)

学习地址

最新完整版Java9-17新特性,只看这一个视频就行了

http://www.dtcms.com/a/289856.html

相关文章:

  • Product Hunt 每日热榜 | 2025-07-20
  • Feign远程调用
  • LWJGL教程(2)——游戏循环
  • VMware中mysql无法连接端口3306不通
  • 暑假训练之动态规划---动态规划的引入
  • PrimeTime:高级片上变化(AOCV)
  • 1948. 删除系统中的重复文件夹
  • 16.TaskExecutor启动
  • Windows批量修改文件属性方法
  • pyhton基础【27】课后拓展
  • 【华为机试】169. 多数元素
  • C++ STL中迭代器学习笔记
  • day057-docker-compose案例与docker镜像仓库
  • 元学习算法的数学本质:从MAML到Reptile的理论统一与深度分析
  • Vision Transformer (ViT) 介绍
  • 面试高频题 力扣 417. 太平洋大西洋水流问题 洪水灌溉(FloodFill) 深度优先遍历(dfs) 暴力搜索 C++解题思路 每日一题
  • 使用unsloth模型微调过程
  • 软件反调试(5)- 基于注册表实时调试器检测
  • MYSQL:从增删改查到高级查询
  • 数据结构-线性表的链式表示
  • 《P3398 仓鼠找 sugar》
  • 【1】YOLOv13 AI大模型-可视化图形用户(GUI)界面系统开发
  • 【实证分析】会计稳健性指标分析-ACF、CScore、Basu模型(2000-2023年)
  • MySQL锁(二) 共享锁与互斥锁
  • Filter快速入门 Java web
  • Compose笔记(三十七)--FilterChip
  • TVLT:无文本视觉-语言Transformer
  • c++ duiLib 显示一个简单的窗口
  • AMD处理器 5700G 矿卡RX580-8G 打英雄联盟怎么样
  • 洛谷 P10287 [GESP样题 七级] 最长不下降子序列-普及/提高-