Java 常用新语法简介

发布时间:2026/7/19 9:47:19
Java 常用新语法简介 参考资料Java 11 升Java 17 重要特性必读Java 21新機能まとめ目录一. 字符串1.1 文本块1.2 String二. Optional 与 Stream三. 集合3.1 .of()方法3.2 SequencedCollection接口四. Switch表达式五. instanceof匹配模式六. 变量七. Record八. 虚拟线程8.1 示例18.2 示例28.3 示例3一. 字符串1.1 文本块JDK15出现的新语法文本块是一个多行字符串它可以避免使用大多数转义符号自动以可预测的方式格式化字符串并让开发人员在需要时可以控制格式。importjava.text.MessageFormat;// 可以看到,无需添加额外的换行符看起来也更加直观Stringcontent 下記情報より入館準備作業をお願い致します。 契約者申請日 {0} 契約社員名 {1} 会社名(BP社員側){2} ※IDカード作成するためBP社員の顔写真は下記アドレスに置いています。 格納先\\\\192.168.255.245\\XXX社内情報\\104_カード全社\\☆☆新規依頼写真格納フォルダ☆☆ ;// 邮件中需要用到的参数String[]params{// {0} 契約者申請日2023/05/16,// {1} 契約社員名贾飞天,// {2} 会社名BP社員側ZY株式会社};StringmailContentMessageFormat.format(content,params);System.out.println(mailContent);/* 下記情報より入館準備作業をお願い致します。 契約者申請日 2023/05/16 契約社員名 贾飞天 会社名(BP社員側)ZY株式会社 ※IDカード作成するためBP社員の顔写真は下記アドレスに置いています。 格納先\\192.168.255.245\XXX社内情報\104_カード全社\☆☆新規依頼写真格納フォルダ☆☆ */也可以使用.formatted()方法来格式化文本块下面这种写法上下两个对齐因此不会产生额外的空格StringnameTom;intage18;Stringtext name : %s age : %d .formatted(name,age);System.out.println(text);1.2 StringJDK11对String增加了新的方法判断是否为空字符串 .isBlank()按行进行切分ListStringlist123\n456.lines().toList();System.out.println(list);// [123, 456]将字符串重负指定的次数-.repeat(10)二. Optional 与 StreamJDK11对Optional进行了增强// JDK11之前!optional.isPresent()// JDK11之后optional.isEmpty()JDK16提供了Stream直接转换为List的方法// JDK16之前的写法ListStringlist1123\n456.lines().collect(Collectors.toList());// JDK16之后的写法ListStringlist2123\n456.lines().toList();三. 集合3.1.of()方法JDK9之后出现的创建集合的工厂方法创建的是不可变集合。List.of(...)Map.of(...)Set.of(...)3.2 SequencedCollection接口Java 中很多集合其实都是有顺序Sequence的例如ArrayListLinkedListVectorArrayDequeLinkedHashSetTreeSet但是它们以前没有统一的接口来表示有顺序Java 21为了解决这个问题引入了SequencedCollection这样所有有顺序的集合都有统一的 API。可以把 SequencedCollection 理解为所有具有确定顺序的集合的统一接口。它最大的价值并不是增加了新的能力而是把 List、Deque、有序 Set 等原本风格不一致的 API 统一了让泛型代码更简洁、更一致。Collection │ └── SequencedCollection │ ├── List ├── Deque └── SortedSet通过 SequencedSet示例如下importjava.util.SequencedCollection;SequencedCollectionStringlistnewArrayList(List.of(A,B,C));Stringfirstlist.getFirst();Stringlastlist.getLast();list.addFirst(Z);list.addLast(D);list.removeFirst();list.removeLast();四. Switch表达式JDK14之后提供的新特性定义一个枚举类importjava.util.Arrays;publicenumCategoryType{老师(1),学生(2),家属(3),外派(4),领导(5),其他(6);privateStringcode;CategoryType(Stringcode){this.codecode;}publicStringgetCode(){returncode;}publicstaticCategoryTypefromCode(Stringcode){returnArrays.stream(CategoryType.values()).filter(item-item.code.equals(code)).findAny().orElse(null);}}使用新的Switch表达式// 成员codeStringtypeCode1;// 根据成员code获取对应的枚举类对象CategoryTypecategoryTypeCategoryType.fromCode(typeCode);Stringresultswitch(categoryType){// 当枚举类的对象为 老师、学生、领导的时候走这个分支case老师,学生,领导-学校内部成员, 该成员的身份为: categoryType.name();case家属,外派-学校外部成员, 该成员的身份为: categoryType.name();case其他-其他成员, 该成员的身份为: categoryType.name();default-该成员不存在;};System.out.println(result);// 学校内部成员, 该成员的身份为: 老师StringdayMON;Stringresultswitch(day){caseMON-工作日;caseSAT,SUN-休息日;default-未知;};System.out.println(result);五. instanceof匹配模式JDK16之后提供的新特性importlombok.Builder;importlombok.Data;DataBuilderpublicclassStudent{privateStringname;privateStringage;privateStringaddress;}// 用过构建者方法创建一个对象,为了测试,将类型指定为Object类型ObjectstudentStudent.builder().age(10).address(地球).name(贾飞天).build();// JDK16之前的写法: 判断之后,需要手动进行转换if(studentinstanceofStudent){Studentstu(Student)student;Stringnamestu.getName();System.out.println(名字是: name);// 名字是: 贾飞天}// JDK16之后的写法: 如果通过类型检查之后,可以自动进行类型转换if(studentinstanceofStudentstu){Stringnamestu.getName();System.out.println(名字是: name);// 名字是: 贾飞天}/** * if条件中有 运算符时,当 instanceof 类型匹配成功,模式局部变量的作用范围也可以相应延长 * 注意: 仅限于 运算符, || 运算符时使用会有问题 */if(studentinstanceofStudentstu!ObjectUtils.isEmpty(stu.getName())){Stringnamestu.getName();System.out.println(名字是: name);// 名字是: 贾飞天}六. 变量JDK10之后使用var关键字的话编译器自动推断类型。varnameTom;varlist1newArrayListString();七. Record详情请参考下面这篇文章Java record类用法简介八. 虚拟线程jdk21新增虚拟线程的目标不是让单个任务执行得更快而是为了提高系统吞吐量Throughput尤其适合I/O密集型任务。传统线程创建一个 Java 线程就会对应创建一个操作系统线程。JavaThread│ ▼OSThread操作系统线程虚拟线程JVM 会自动把大量虚拟线程调度到少量真正的操作系统线程上运行。创建线程几乎没有成本可以创建几十万甚至几百万个线程非常适合大量 I/O 操作VirtualThread│ ▼JVMScheduler│ ▼ 少量OSThreadCarrierThread// 例如:100000个VirtualThread│ ▼8个OSThread8.1 示例1try(var executorExecutors.newVirtualThreadPerTaskExecutor()){IntStream.range(0, 10_000).forEach(i -{executor.submit(()-{ Thread.sleep(Duration.ofSeconds(1));returni;});});}8.2 示例2publicclassOrderService{publicvoidcreateOrder(){checkStock();pay();sendSms();System.out.println(订单完成);}privatevoidcheckStock(){sleep(1000);System.out.println(库存检查完成);}privatevoidpay(){sleep(2000);System.out.println(支付完成);}privatevoidsendSms(){sleep(1000);System.out.println(短信发送完成);}privatevoidsleep(longms){try{Thread.sleep(ms);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}publicvoidprocessOrder(intid,OrderServiceservice){System.out.println(开始处理订单id);service.createOrder();System.out.println(订单完成id);}try(ExecutorServiceexecutorExecutors.newVirtualThreadPerTaskExecutor()){OrderServiceservicenewOrderService();for(inti1;i10000;i){intidi;executor.submit(()-processOrder(id,service));}}8.3 示例3publicStringgetUser()throwsException{Thread.sleep(2000);return用户信息;}publicStringgetOrder()throwsException{Thread.sleep(2000);return订单信息;}publicStringgetPoint()throwsException{Thread.sleep(2000);return积分信息;}try(ExecutorServiceexecutorExecutors.newVirtualThreadPerTaskExecutor()){FutureStringuserexecutor.submit(()-getUser());FutureStringorderexecutor.submit(()-getOrder());FutureStringpointexecutor.submit(()-getPoint());for(inti1;i1000000;i){StringuserInfouser.get();StringuserOrderorder.get();StringuserPointpoint.get();System.out.println(userInfo userOrder userPoint);}}