JDK17都出来了,你还在用JDK8?
JDK17的一些新特性
本文旨在介绍一些JDK17的新特性,同时限于篇幅,本文仅列举其中一些差异,而不是全部差异;
PS: JDK17是Java的一个LTS版本(长期支持版本),可以放心迁移过来;
instanceof
JDK8中的语法:
Object o = something; if (o instanceof String) { String str = (String)o; // do something }
在JDK17中我们可以这样写:
Object o = something; if (o instanceof String str) { // do something, 注意上边String后边跟了一个str,相当于把o强转为String同时使用变量名str引用,我们后续可以直接使用str而不用再加一层强转了 }
switch
普通switch
如果switch中只有一条语句时,JDK8中的语法:
String str = something; switch (str) { case "123": System.out.println(str); break; case "456": System.out.println(str); break; }
可以看出每个case后边都需要一个 break
,否则会穿透到后边的 case
语句;
JDK17中的语法:
String str = something; switch (str) { case "123" -> System.out.println(str); case "456" -> System.out.println(str); default -> System.out.println(str); }
switch的模式匹配
JDK8中的语法:
Object o = something; if (o instanceof String) { String str = (String)o; // do something } else if (o instanceof Integer) { Integer integer = (Integer)o; // do something }
在JDK17中我们可以这样写(case语句也可以展开,这里为了省事就用了这种写法):
Object o = something; switch (o) { case Integer i -> System.out.println(i); case String str -> System.out.println(str); default -> System.out.println(o); }
null值处理
传统(JDK8)switch语句需要提前判null,否则会抛出NPE:
String str = something; if (str == null) { // do something return; } switch (str) { case "123": System.out.println(str); break; case "456": System.out.println(str); break; }
JDK17中无需判空,可以直接 case null
:
String str = something; switch (str) { case null -> System.out.println("null"); case "123" -> System.out.println(str); case "456" -> System.out.println(str); default -> System.out.println(str); }
复杂条件的case优化:
对于以下代码:
class Shape {} class Rectangle extends Shape {} class Triangle extends Shape { int calculateArea() { ... } } static void testTriangle(Shape s) { switch (s) { case null: break; case Triangle t: if (t.calculateArea() > 100) { System.out.println("Large triangle"); break; } default: System.out.println("A shape, possibly a small triangle"); } }
可以优化为:
class Shape {} class Rectangle extends Shape {} class Triangle extends Shape { int calculateArea() { ... } } static void testTriangle(Shape s) { switch (s) { case Triangle t && (t.calculateArea() > 100) -> System.out.println("Large triangle"); default -> System.out.println("A shape, possibly a small triangle"); } }
密封类(sealed Class)
在JDK8中,如果我们一个类只想要只想要指定的子类(我们自己编写的类)实现,而不希望其他依赖方自己实现(这种场景在框架编写中很常见),我们通常的方法是将构造器设置为私有的,然后使用 静态内部类来继承该类,或者将构造器设置为package访问级别的,然后在同一个包中编写类来继承;这两种方式虽然都能实现我们的目标(在某些场景也能被打破,例如用户自己编写了一个同名包,然 后就能在包中继续继承该类了),但是都不是太优雅,在我们升级JDK17后该问题也将被解决,JDK17中引入了一个新的关键字 sealed
用来修饰我们不想要其他人私自继承的类(或者接口),然后使用 permits
关键字指定都有那些类可以继承本类,用法如下:
public abstract sealed class TestA permits TestB { } public class TestB extends TestA { }
这里我们使用 sealed
关键字声明 TestA
不能随便被其他类继承,然后使用 permits
声明只有 TestB
才能继承 TestA
,注意,这里 TestB
和 TestA
必须在同一个包中,如 果不在同一个包中,那么 permits
关键字后的 TestB
必须带包名(例如com.JoeKerouac.TestB);
联系我
- 作者微信:JoeKerouac
- 微信公众号(文章会第一时间更新到公众号):代码深度研究院
- GitHub:https://github.com/JoeKerouac
参考文献
- jdk17完整发布变更说明文档(注:截止文章发布时该地址仍有效,后续JDK继续升级,JDK17被归档后该地址可能无效):https://jdk.java.net/17/release-notes
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: JDK17都出来了,你还在用JDK8?
jjjjj
support!