关于java:卷不动了300-秒快速了解-Java-9-16-新特性助你脱离内卷

点赞再看,养成好习惯

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.NullPointerException
    at 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 null
    at 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 目前这个驴一样的更新频率,很可能下个版本就是稳定版了。

看看工夫,300 秒到了吗?

​> 原创不易,禁止未受权的转载。如果我的文章对您有帮忙,就请点赞/珍藏/关注激励反对一下吧❤❤❤❤❤❤

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据