快速了解 Java 9 - 16 新特性,助你脱离内卷

2024-09-02 08:48
文章标签 java 16 特性 快速 了解 脱离

本文主要是介绍快速了解 Java 9 - 16 新特性,助你脱离内卷,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方“朱小厮的博客”,选择“设为星标”

后台回复"书",获取

后台回复“k8s”,可领取k8s资料

JAVA 这几年的更新实在是太太太……快了,JAVA 8 都还没用多久,16 都已经发布了。自从 JAVA 8 发布了 Lambda 和 Stream 之后,JAVA 就像打了鸡血一样,半年一个版本的发布,生产队的驴也没这么勤快。

导致我们现在完全跟不上 JAVA 发布的节奏,我司目前还停留在 JAVA 8,甚至部分老系统还在使用 JAVA 7,根本不能轻易的升级。

不过虽然暂时用不上最新版本的 JAVA,但了解每个新版本的主要特性还是很重要的,不然哪天真跟着升级了,那还不得一脸懵逼。

本文就带你快速了解 JAVA 9 - 16 的主要新特性,早学完早下班!

JAVA 9(2017年9月)

接口里可以添加私有接口

JAVA 8 对接口增加了默认方法的支持,在 JAVA 9 中对该功能又来了一次升级,现在可以在接口里定义私有方法,然后在默认方法里调用接口的私有方法。

这样一来,既可以重用私有方法里的代码,又可以不公开代码

public interface TestInterface {default void wrapMethod(){innerMethod();}private void innerMethod(){System.out.println("");}
}

匿名内部类也支持钻石(diamond)运算符

JAVA 5 就引入了泛型(generic),到了 JAVA 7 开始支持钻石(diamond)运算符:<>,可以自动推断泛型的类型:

List<Integer> numbers = new ArrayList<>();

但是这个自动推断类型的钻石运算符可不支持匿名内部类,在 JAVA 9 中也对匿名内部类做了支持:

List<Integer> numbers = new ArrayList<>() {...
}

增强的 try-with-resources

JAVA 7 中增加了try-with-resources的支持,可以自动关闭资源:

try (BufferedReader bufferReader = new BufferedReader(...)) {return bufferReader.readLine();
}

但需要声明多个资源变量时,代码看着就有点恶心了,需要在 try 中写多个变量的创建过程:

try (BufferedReader bufferReader0 = new BufferedReader(...);BufferedReader bufferReader1 = new BufferedReader(...)) {return bufferReader0.readLine();
}

JAVA 9 中对这个功能进行了增强,可以引用 try 代码块之外的变量来自动关闭:

BufferedReader bufferReader0 = new BufferedReader(...);
BufferedReader bufferReader1 = new BufferedReader(...);
try (bufferReader0; bufferReader1) {System.out.println(br1.readLine() + br2.readLine());
}

JAVA 10(2018年3月)

局部变量的自动类型推断(var)

JAVA 10 带来了一个很有意思的语法 - var,它可以自动推断局部变量的类型,以后再也不用写类型了,也不用靠 lombok 的 var 注解增强了

var message = "Hello, Java 10";

不过这个只是语法糖,编译后变量还是有类型的,使用时还是考虑下可维护性的问题,不然写多了可就成 JavaScript 风格了

JAVA 11(2018年9月)

Lambda 中的自动类型推断(var)

JAVA 11 中对 Lambda 语法也支持了 var 这个自动类型推断的变量,通过 var 变量还可以增加额外的注解:

List<String> languages = Arrays.asList("Java", "Groovy");
String language = sampleList.stream().map((@Nonnull var x) -> x.toUpperCase()).collect(Collectors.joining(", "));assertThat(language).isEqualTo("Java, Groovy");

javac + java 命令一把梭

以前编译一个 java 文件时,需要先 javac 编译为 class,然后再用 java 执行,现在可以一把梭了:

$ java HelloWorld.java
Hello Java 11!

Java Flight Recorder 登陆 OpenJDK

Java Flight Recorder 是个灰常好用的调试诊断工具,不过之前是在 Oracle JDK 中,也跟着 JDK 11 开源了,OpenJDK 这下也可以用这个功能,真香!

JAVA 12(2019年3月)

更简洁的 switch 语法

在之前的 JAVA 版本中,switch 语法还是比较啰嗦的,如果多个值走一个逻辑需要写多个 case

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
String typeOfDay = "";
switch (dayOfWeek) {case MONDAY:case TUESDAY:case WEDNESDAY:case THURSDAY:case FRIDAY:typeOfDay = "Working Day";break;case SATURDAY:case SUNDAY:typeOfDay = "Day Off";
}

到了 JAVA 12,这个事情就变得很简单了,几行搞定,而且!还支持返回值:

typeOfDay = switch (dayOfWeek) {case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";case SATURDAY, SUNDAY -> "Day Off";
};

instanceof + 类型强转一步到位

之前处理动态类型碰上要强转时,需要先 instanceof 判断一下,然后再强转为该类型处理:

Object obj = "Hello Java 12!";
if (obj instanceof String) {String s = (String) obj;int length = s.length();
}

现在 instanceof 支持直接类型转换了,不需要再来一次额外的强转:

Object obj = "Hello Java 12!";
if (obj instanceof String str) {int length = str.length();
}

JAVA 13(2019年9月)

switch 语法再增强

JAVA 12 中虽然增强了 swtich 语法,但并不能在 -> 之后写复杂的逻辑,JAVA 12 带来了 swtich更完美的体验,就像 lambda 一样,可以写逻辑,然后再返回:

typeOfDay = switch (dayOfWeek) {case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {// do sth...yield "Working Day";}case SATURDAY, SUNDAY -> "Day Off";
};

文本块(Text Block)的支持

你是否还在为大段带换行符的字符串报文所困扰,换行吧一堆换行符,不换行吧看着又难受:

String json = "{\"id\":\"1697301681936888\",\"nickname\":\"空无\",\"homepage\":\"https://juejin.cn/user/1697301681936888\"}";

JAVA 13 中帮你解决了这个恶心的问题,增加了文本块的支持,现在可以开心的换行拼字符串了,就像用模板一样:

String json = """{"id":"1697301681936888","nickname":"空无","homepage":"https://juejin.cn/user/1697301681936888"}""";

JAVA 14(2020年3月)

新增的 record 类型,干掉复杂的 POJO 类

一般我们创建一个 POJO 类,需要定义属性列表,构造函数,getter/setter,比较麻烦。JAVA 14 为我们带来了一个便捷的创建类的方式 - record

public record UserDTO(String id,String nickname,String homepage) { };public static void main( String[] args ){UserDTO user = new UserDTO("1697301681936888","空无","https://juejin.cn/user/1697301681936888");System.out.println(user.id);System.out.println(user.nickname);System.out.println(user.id);
}

IDEA 也早已支持了这个功能,创建类的时候直接就可以选:

不过这个只是一个语法糖,编译后还是一个 Class,和普通的 Class 区别不大

更直观的 NullPointerException 提示

NullPointerException 算是 JAVA 里最常见的一个异常了,但这玩意提示实在不友好,遇到一些长一点的链式表达式时,没办法分辨到底是哪个对象为空。

比如下面这个例子中,到底是 innerMap 为空呢,还是 effected 为空呢?

Map<String,Map<String,Boolean>> wrapMap = new HashMap<>();
wrapMap.put("innerMap",new HashMap<>());boolean effected = wrapMap.get("innerMap").get("effected");// StackTrace:
Exception in thread "main" java.lang.NullPointerExceptionat org.example.App.main(App.java:50)

JAVA 14 也 get 到了 JAVAER 们的痛点,优化了 NullPointerException 的提示,让你不在困惑,一眼就能定位到底“空”在哪!

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "java.util.Map.get(Object)" is nullat org.example.App.main(App.java:50)

现在的 StackTrace 就很直观了,直接告诉你 effected 变量为空,再也不用困惑!

安全的堆外内存读写接口,别再玩 Unsafe 的骚操作了

在之前的版本中,JAVA 如果想操作堆外内存(DirectBuffer),还得 Unsafe 各种 copy/get/offset。现在直接增加了一套安全的堆外内存访问接口,可以轻松的访问堆外内存,再也不用搞 Unsafe 的骚操作了。

// 分配 200B 堆外内存
MemorySegment memorySegment = MemorySegment.allocateNative(200);// 用 ByteBuffer 分配,然后包装为 MemorySegment
MemorySegment memorySegment = MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect(200));// MMAP 当然也可以
MemorySegment memorySegment = MemorySegment.mapFromPath(Path.of("/tmp/memory.txt"), 200, FileChannel.MapMode.READ_WRITE);// 获取堆外内存地址
MemoryAddress address = MemorySegment.allocateNative(100).baseAddress();// 组合拳,堆外分配,堆外赋值
long value = 10;
MemoryAddress memoryAddress = MemorySegment.allocateNative(8).baseAddress();
// 获取句柄
VarHandle varHandle = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder());
varHandle.set(memoryAddress, value);// 释放就这么简单,想想 DirectByteBuffer 的释放……多奇怪
memorySegment.close();

不了解 Unsafe 操作堆外内存方式的同学,可以参考我的另一篇文章《JDK中为了性能大量使用的Unsafe类,你会用吗?》

新增的 jpackage 打包工具,直接打包二进制程序,再也不用装 JRE 了

之前如果想构建一个可执行的程序,还需要借助三方工具,将 JRE 一起打包,或者让客户电脑也装一个 JRE 才可以运行我们的 JAVA 程序。

现在 JAVA 直接内置了 jpackage 打包工具,帮助你一键打包二进制程序包,终于不用乱折腾了

JAVA 15(2020年9月)

ZGC 和 Shenandoah 两款垃圾回收器正式登陆

在 JAVA 15中,ZGC 和 Shenandoah 再也不是实验功能,正式登陆了(不过 G1 仍然是默认的)。如果你升级到 JAVA 15 以后的版本,就赶快试试吧,性能更强,延迟更低

封闭(Sealed )类

JAVA 的继承目前只能选择允许继承和不允许继承(final 修饰),现在新增了一个封闭(Sealed )类的特性,可以指定某些类才可以继承:

public sealed interface Service permits Car, Truck {int getMaxServiceIntervalInMonths();default int getMaxDistanceBetweenServicesInKilometers() {return 100000;}}

JAVA 16(2021年3月)

JAVA 16 在用户可见的地方变化并不多,基本都是 14/15 的实验性内容,到了 16 正式发布,这里就不重复介绍了。

总结

以上介绍的各种新特性,有些特性在历史版本中还属于实验性功能,不过按照 JAVA 目前这个驴一样的更新频率,很可能下个版本就是稳定版了。早学早享受,晚学被卷走……

来源 | https://juejin.cn/post/6964543834747322405

想知道更多?描下面的二维码关注我

后台回复"技术",加入技术群

后台回复“k8s”,可领取k8s资料

【精彩推荐】

  • ClickHouse到底是什么?为什么如此牛逼!

  • 原来ElasticSearch还可以这么理解

  • 面试官:InnoDB中一棵B+树可以存放多少行数据?

  • 架构之道:分离业务逻辑和技术细节

  • 星巴克不使用两阶段提交

  • 面试官:Redis新版本开始引入多线程,谈谈你的看法?

  • 喜马拉雅自研网关架构演进过程

  • 收藏:存储知识全面总结

  • 微博千万级规模高性能高并发的网络架构设计

这篇关于快速了解 Java 9 - 16 新特性,助你脱离内卷的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129520

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C