Java 常用新语法简介
📅 2026/7/19 9:53:54
👁️ 阅读次数
📝 编程学习
参考资料
- Java 11 升Java 17 重要特性必读
- Java 21新機能まとめ
目录
- 一. 字符串
- 1.1 文本块
- 1.2 String
- 二. Optional 与 Stream
- 三. 集合
- 3.1 `.of()`方法
- 3.2 SequencedCollection接口
- 四. Switch表达式
- 五. instanceof匹配模式
- 六. 变量
- 七. Record
- 八. 虚拟线程
- 8.1 示例1
- 8.2 示例2
- 8.3 示例3
一. 字符串
1.1 文本块
🔷JDK15出现的新语法
- 文本块,是一个多行字符串,它可以避免使用大多数转义符号,自动以可预测的方式格式化字符串,并让开发人员在需要时可以控制格式。
importjava.text.MessageFormat;// 可以看到,无需添加额外的换行符,看起来也更加直观Stringcontent=""" 下記情報より入館準備作業をお願い致します。 (1)契約者申請日: {0} (2)契約社員名: {1} (3)会社名(BP社員側):{2} ※IDカード作成するためBP社員の顔写真は下記アドレスに置いています。 格納先:\\\\192.168.255.245\\XXX社内情報\\104_IDカード(全社)\\☆☆新規依頼ID写真格納フォルダ☆☆ """;// 邮件中需要用到的参数String[]params={// {0} => 契約者申請日"2023/05/16",// {1} => 契約社員名"贾飞天",// {2} => 会社名(BP社員側)"ZY株式会社"};StringmailContent=MessageFormat.format(content,params);System.out.println(mailContent);/* 下記情報より入館準備作業をお願い致します。 (1)契約者申請日: 2023/05/16 (2)契約社員名: 贾飞天 (3)会社名(BP社員側):ZY株式会社 ※IDカード作成するためBP社員の顔写真は下記アドレスに置いています。 格納先:\\192.168.255.245\XXX社内情報\104_IDカード(全社)\☆☆新規依頼ID写真格納フォルダ☆☆ */- 也可以使用
.formatted()方法来格式化文本块 - 下面这种写法,上下两个
"""对齐,因此不会产生额外的空格
Stringname="Tom";intage=18;Stringtext=""" name : %s age : %d """.formatted(name,age);System.out.println(text);1.2 String
🔷JDK11对String增加了新的方法
- 判断是否为空字符串
" ".isBlank()- 按行进行切分
List<String>list="123\n456".lines().toList();System.out.println(list);// [123, 456]- 将字符串重负指定的次数
"-".repeat(10)二. Optional 与 Stream
🔷JDK11对Optional进行了增强
// JDK11之前!optional.isPresent()// JDK11之后optional.isEmpty()🔷JDK16提供了Stream直接转换为List的方法
// JDK16之前的写法List<String>list1="123\n456".lines().collect(Collectors.toList());// JDK16之后的写法List<String>list2="123\n456".lines().toList();三. 集合
3.1.of()方法
🔷JDK9之后出现的创建集合的工厂方法,创建的是不可变集合。
List.of(...)Map.of(...)Set.of(...)3.2 SequencedCollection接口
Java 中很多集合其实都是有顺序(Sequence)的,例如:
- ArrayList
- LinkedList
- Vector
- ArrayDeque
- LinkedHashSet
- TreeSet
但是它们以前没有统一的接口来表示有顺序,Java 21为了解决这个问题,引入了SequencedCollection,这样所有有顺序的集合都有统一的 API。
可以把 SequencedCollection 理解为所有具有确定顺序的集合的统一接口。它最大的价值并不是增加了新的能力,而是把 List、Deque、有序 Set 等原本风格不一致的 API 统一了,让泛型代码更简洁、更一致。
Collection │ └── SequencedCollection │ ├── List ├── Deque └── SortedSet(通过 SequencedSet)- 示例如下:
importjava.util.SequencedCollection;SequencedCollection<String>list=newArrayList<>(List.of("A","B","C"));Stringfirst=list.getFirst();Stringlast=list.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.code=code;}publicStringgetCode(){returncode;}publicstaticCategoryTypefromCode(Stringcode){returnArrays.stream(CategoryType.values()).filter(item->item.code.equals(code)).findAny().orElse(null);}}- 使用新的Switch表达式
// 成员codeStringtypeCode="1";// 根据成员code获取对应的枚举类对象CategoryTypecategoryType=CategoryType.fromCode(typeCode);Stringresult=switch(categoryType){// 当枚举类的对象为 老师、学生、领导的时候,走这个分支case老师,学生,领导->"学校内部成员, 该成员的身份为: "+categoryType.name();case家属,外派->"学校外部成员, 该成员的身份为: "+categoryType.name();case其他->"其他成员, 该成员的身份为: "+categoryType.name();default->"该成员不存在";};System.out.println(result);// 学校内部成员, 该成员的身份为: 老师Stringday="MON";Stringresult=switch(day){case"MON"->"工作日";case"SAT","SUN"->"休息日";default->"未知";};System.out.println(result);五. instanceof匹配模式
🔷JDK16之后提供的新特性
importlombok.Builder;importlombok.Data;@Data@BuilderpublicclassStudent{privateStringname;privateStringage;privateStringaddress;}// 用过构建者方法创建一个对象,为了测试,将类型指定为Object类型Objectstudent=Student.builder().age("10").address("地球").name("贾飞天").build();// JDK16之前的写法: 判断之后,需要手动进行转换if(studentinstanceofStudent){Studentstu=(Student)student;Stringname=stu.getName();System.out.println("名字是: "+name);// 名字是: 贾飞天}// JDK16之后的写法: 如果通过类型检查之后,可以自动进行类型转换if(studentinstanceofStudentstu){Stringname=stu.getName();System.out.println("名字是: "+name);// 名字是: 贾飞天}/** * if条件中有 && 运算符时,当 instanceof 类型匹配成功,模式局部变量的作用范围也可以相应延长 * 注意: 仅限于 && 运算符, || 运算符时使用会有问题 */if(studentinstanceofStudentstu&&!ObjectUtils.isEmpty(stu.getName())){Stringname=stu.getName();System.out.println("名字是: "+name);// 名字是: 贾飞天}六. 变量
🔷JDK10之后,使用var关键字的话,编译器自动推断类型。
varname="Tom";varlist1=newArrayList<String>();七. Record
🔷详情请参考下面这篇文章:
- Java record类用法简介
八. 虚拟线程
🔷jdk21新增,虚拟线程的目标不是让单个任务执行得更快,而是为了提高系统吞吐量(Throughput),尤其适合I/O密集型任务。
- 传统线程:创建一个 Java 线程,就会对应创建一个操作系统线程。
JavaThread│ ▼OSThread(操作系统线程)- 虚拟线程:JVM 会自动把大量虚拟线程调度到少量真正的操作系统线程上运行。
- 创建线程几乎没有成本
- 可以创建几十万甚至几百万个线程
- 非常适合大量 I/O 操作
VirtualThread│ ▼JVMScheduler│ ▼ 少量OSThread(CarrierThread)// 例如:100000个VirtualThread│ ▼8个OSThread8.1 示例1
try(var executor=Executors.newVirtualThreadPerTaskExecutor()){IntStream.range(0, 10_000).forEach(i ->{executor.submit(()->{ Thread.sleep(Duration.ofSeconds(1));returni;});});}8.2 示例2
publicclassOrderService{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(ExecutorServiceexecutor=Executors.newVirtualThreadPerTaskExecutor()){OrderServiceservice=newOrderService();for(inti=1;i<=10000;i++){intid=i;executor.submit(()->processOrder(id,service));}}8.3 示例3
publicStringgetUser()throwsException{Thread.sleep(2000);return"用户信息";}publicStringgetOrder()throwsException{Thread.sleep(2000);return"订单信息";}publicStringgetPoint()throwsException{Thread.sleep(2000);return"积分信息";}try(ExecutorServiceexecutor=Executors.newVirtualThreadPerTaskExecutor()){Future<String>user=executor.submit(()->getUser());Future<String>order=executor.submit(()->getOrder());Future<String>point=executor.submit(()->getPoint());for(inti=1;i<=1000000;i++){StringuserInfo=user.get();StringuserOrder=order.get();StringuserPoint=point.get();System.out.println(userInfo+" "+userOrder+" "+userPoint);}}
编程学习
技术分享
实战经验