Java18都在路上了,你还在用Java8吗

Java18都快推出了,还有很多的小伙伴可能还在用Java8,可能还不知道很多高版本提供的一些好用的特性,下面我整理了一下从Java9~Java17中我个人觉得一些比较实用的特性,让大家在推动公司Java版本的升级时有更多的理由。

可能很多公司会为了“稳定性”而拒绝升级高版本的JDK,就和以前Java8刚推出时,还在用JDK1.6的人拒绝升级一样。但实际上是有多少是真的为了稳定性,还有多少只是公司单纯的拒绝新的技术,这谁知道呢?^ _ ^

一些特性

JEP 286: Local-Variable Type Inference(Java11)

变量类型推导,可以让我们在使用局部变量时,使用var关键字来定义一个变量:

var list = new ArrayList<String>();
复制代码

这个算是一个我比较喜欢且最常用的一个特性了,可以显著的简化代码,但是也会带来一个问题:可读性下降。该如何使用,看个人权衡了。

JEP 358: Helpful NullPointerExceptions(Java14)

我相信大部分人的处理NPE时都会遇到的一个令人头疼的问题,那就是报NPE的那行是一个链式调用,比如:

class Main {
    public static void main(String[] args) {
        var x = a().b().i.j;
    }
}
Exception in thread "main" java.lang.NullPointerException:
    at Main.main(Main.java:3)
复制代码

这样的NPE异常毫无指向性,你可能根本不知道是哪个方法或变量报的异常。而在Java14及以后,NPE将会变得更加有的指向性,还是同样的代码,在Java14中的异常则会是:

Exception in thread "main" java.lang.NullPointerException:
	Cannot read field "j" because "i" is null
    at Main.main(Main.java:3)
复制代码

这可以让我们在排查问题时,可以更清晰的定位问题。

 扫VX 领Java资料,前端,测试,python等等资料都有

JEP 361: Switch Expressions(Java14)

更优雅、更简洁的Switch表达式,再也不用写一堆的CASE/BREAK 了

switch(month) {
    case 1,3,5,7,8,10,12 -> System.out.println("31");
    case 4,6,9,11 -> System.out.println("30");
    case 2 -> System.out.println("28");
};
复制代码

switch也可以当作表达式使用,即可以提供返回值:

var x = switch(condition) {
    case A -> "a";
    case B -> "b";
    default -> "none";
};
复制代码

新增的yield关键字还可以让你在表达式中处理一大段的代码块:

var x = switch(condition) { 
    case A -> "a";
    case B -> "b";
    default -> {
	Sytem.out.println("in default");
	//do something else
	var result = doSomething();
	yield result;
    }
};
复制代码

JEP 378: Text Blocks(Java15)

终于终于终于可以不用在字符串中处理一堆的反斜杆,\n, +号拼接了!!
简单的看一个对比:

var script = "function hello() {\n" +
                         "    print('\"Hello, world\"');\n" +
                         "}\n" +
                         "\n" +
                         "hello();\n"
复制代码

Java15及以后:

var script = """
		function hello() {
        	    print('"Hello, world"');
    		}
                        
    		hello();
	     """
复制代码

可读性相差太多了,如此简单、常用的基础能力,早就应该提供了!你也可以像和普通字符串一样,使用占位符和format方法。

JEP 395: Records(Java16) 数据类,有点类似于Kotlin中的data object. 可以使用下面的方式来定义一个数据类:

public record Data(int x, int y) {
}
复制代码

这个类会默认实现hashCode()、equals()和toString()方法,并且这个类被被定义为final,并且不可变:字段初始化后即不可再修改。在类里面也可以定义普通或静态方法。

在我们需要返回一些不可变的数据给外部使用时,可以使用record来定义数据格式,在SpringBoot 2.5.0-M1之后(或者升级jackson版本),也提供对Java16的支持,这意味着你可以在spring部分场景中使用,比如controller接收参数时,参数可以是一个record类。

JEP 394: Pattern Matching for instanceof(Java16)

模式匹配,或者说是类型匹配,这也是在Kotlin中已有的功能,可以让我们在编码时少做一些强制类型转换的工作:

if (obj instanceof String) {
    String s = (String) obj;
    s.toLowerCase();
}
复制代码

Java16及以后:

if (obj instanceof String) {
    //自动类型推导
    obj.toLowerCase();
}

//甚至可以这么用
var isGood = obj instanceof String && obj.trim().toLowerCase().equals("good");
复制代码

怎么说呢,在一些场景下,一直做类型强制转换也是挺麻烦的一件事情,这个特性起码可以减少一些编码的工作量。

JEP 409: Sealed Classes(Java17)

提供一种新的约束条件给类或接口,这个一般场景下可能用不上,但是让我们需要写一个框架,或者需要写一个SDK给其它部门或者用户使用的时候,这个特性就可以派上用场了。举个栗子:

public abstract sealed InnerAbsClass permits InnerClassA, InnerClassB {
}
复制代码

当一个类被sealed修饰之后,那么只有被permits关键字指定的名可以继承这个抽象类,其它的类如果尝试继承这个抽象类则会在编译时就会报异常。

还有一种方式是不使permits关键字,那么就只能在同个文件内定义子类:

public abstract sealed InnerAbsClass {
}
public final InnerClassA extends InnerAbsClass {}
public final InnerClassB extends InnerAbsClass {}
复制代码

接口也可以使用同样的方式来定义。

为什么不使用“包访问权限”来限制继承或实现?有些场景我们虽然希望父类不被外部使用者所继承,但是同时也希望他可以被访问,比如提供了一些静态的变量、静态方法可以被外部使用。

总结

上面并不是所有的特性,但是是我个人实际使用过,也觉得确实好用,提高了生产力的一些功能,也分享给大家,说不定还在使用低版本Java的人看到了之后,也决定推动公司升级了呢。 而且Java17是Oracle提供的一个长期支持版本,最多可以支持到 2029年9月份,长达8年的支持起码也可以保障它的稳定性。

最后,追求稳定没有任何问题,但是拥抱新的变化也不错~

 扫VX 领Java资料,前端,测试,python等等资料都有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值