前言

Java8出来这么多年后,已经成为企业最成熟稳定的版本,相信绝大部分公司用的还是这个版本,但是一眨眼今年Java19都出来了,相信很多Java工程师忙于学习工作对新特性没什么了解,有的话也仅限于某一块。



本篇就是博主对自己感觉有用的新特性做了一个案例验证及简要说明,整合起来分享给大家。



特别说明:Java17是继Java8之后的一个重要里程碑,像SpringBoot3.0、IDEA2022、Jenkins新版、Kafka3.0等等很多生态都强制绑定支持这个版本,等于是给它背书,博主建议大家有必要花时间去了解一下。



如果没时间看,可以先收藏一下,闲下来一边喝茶一边品读。

你的收获

首先,你能通过一篇简单、连续、直观的文章就明白Java8之后Java未来整体发展的趋势,为之后几年适应Java相关工作打下基础;



其次,你可以通过了解Java9-17的新特性,为以后的面试加分,毕竟一个爱学习有态度的程序员会更受企业青睐;



最后,你可以看看博主对Java未来发展趋势的粗浅看法,也许能给迷茫的你带来收获。

准备工作

首先,你要安装Java17版本,环境变量配置还是和以前没区别,这是我的版本。

其次,建议安装IDEA2022.3,新版IDEA占用内存比以前少很多,而且有一些增强支持。

安装好后,需要做一个对Java17的配置,看图。

setting配置

Project Structure配置

这里特别说明一下,最好选择预览版本,因为Java17包含一些预览功能,这里不选预览版本会编译报错。

新特性

一共分为了8个,按照版本顺序来讲述的,最后一个是因为几个版本连续有增强,所以单独拿出来。

1、接口private

1)、说明

Java9新特性,在接口中声明private方法,不会被外部实现。

2)、案例

声明一个接口,一个default方法,两个private方法。

/**
* <p>
* 用户信息接口
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 15:03
*/
public interface UserInterface {
private void getUsername() {
System.err.println("你好,我是王小飞!");
} private void getPassword() {
System.err.println("你好,我是徐西圆!");
} default void getData() {
getUsername();
getPassword();
}
}

实现这个接口,可以看到只能实现default方法,无法实现private方法。

/**
* <p>
* JDK9新特性:接口private方法
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 15:10
*/
public class UserImpl implements UserInterface { @Override
public void getData() {
UserInterface.super.getData();
} public static void main(String[] args) {
UserImpl user = new UserImpl();
user.getData();
}
}

Ctrl+Insert可以查看要实现的方法

3)、注意

private接口自动是default的,所以要有方法体,否则编译不通过。

2、类型推断

1)、说明

Java11新特性,在方法内部用var关键字声明一个属性或对象,可以被编译器自动判断类型。

2)、案例

案例包含两个测试,一个是直接测试var声明的变量是否能自己推断类型,一个是在循环中使用的效果。

/**
* <p>
* JDK11新特性:类型推断
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 11:52
*/
public class TypeInferenceDemo { public static void main(String[] args) {
TypeInferenceDemo demo = new TypeInferenceDemo();
// 测试类型推断
// demo.testVar(); // 循环中使用
List<UserInfo> userList = new ArrayList<>();
UserInfo userInfo = new UserInfo();
userInfo.setUsername("张三");
userInfo.setPassword("123456");
userList.add(userInfo);
for (var user : userList) {
System.err.println(user.getUsername() + " | " + user.getPassword());
}
} public void testVar() {
var name = "张三";
var age = 33;
var id = 1001L;
var amount = BigDecimal.ZERO;
var user = new UserInfo();
System.err.println("-------------------------------------------------");
System.err.println(name);
System.err.println(age);
System.err.println(id);
System.err.println(amount);
System.err.println(user);
} public static class UserInfo {
private String username;
private String password; public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}
}

测试的效果如图

3)、注意

1)、只能在方法内部使用(局部变量);

2)、必须有初始化值且不能为null;

3)、不能定义为方法的返回类型。

3、空指针优化

1)、说明

Java15新特性,就是把NullPointerException异常的日志做了优化打印的更人性化。

2)、案例

可以看到,提示会更有指向性,意味着以后在复杂的生产环境排错过程中,你很可能不会再被空指针异常所困扰。

3)、注意

没什么可注意的

4、文本块

1)、说明

JDK15新特性,就是替代了以前String中一堆换行符和双引号的简洁版写法,相信你很难不喜欢。

2)、案例

可以看到,就是三引号取代了双引号,因为双引号的内容会夹带一堆换行符,而三引号里面就单纯是内容,很清晰,而且双引号换行需要杠n,而三引号直接换行即可生效。

/**
* <p>
* JDK15新特性:文本块
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 23:36
*/
public class TextBlockDemo {
private static final String str =
"本以为大S和汪小菲的事情就这样告一段落,彼此都过着属于自己的幸福小日子,但是,被骂9天后,汪小菲口中的“窝囊废”,终于有所行动了!\n"
+ "\n"
+ "也许具俊晔再也忍受不了别人骂自己窝囊废,更不愿意住在别人房子内,所以11月30日,据媒体爆料,具俊晔这次要男人一把,决定买一套属于自己的房子,"
+ "属于自己的床垫,搬出汪小菲买的豪宅,来证明自己的实力。"; private static final String newStr = """
本以为大S和汪小菲的事情就这样告一段落,彼此都过着属于自己的幸福小日子,但是,被骂9天后,汪小菲口中的“窝囊废”,终于有所行动了! 也许具俊晔再也忍受不了别人骂自己窝囊废,更不愿意住在别人房子内,所以11月30日,据媒体爆料,具俊晔这次要男人一把,决定买一套属于自己的房子,
属于自己的床垫,搬出汪小菲买的豪宅,来证明自己的实力。
"""; public static void main(String[] args) {
System.err.println(str);
System.err.println("------------------------------------------------");
System.err.println(newStr);
}
}
3)、注意

文本块只有一个要注意的地方,就是默认三引号内的内容没有缩进,想要缩进的话要以末尾三引号为参照物向后偏移来确定缩进量。



下面一张图会直接展示给你效果:

5、智能转型

1)、说明

Java16新特性,就是帮你对instanceof做了增强,智能转换变量类型。

2)、案例

可以对比old和new两种写法,第二种就是将第一种简化了,类型转换+声明变量+后续逻辑判断一起搞定。

/**
* <p>
* JDK16新特性:智能转型
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/3 14:02
*/
public class InstanceofMatching {
/**
* 旧写法
* @param obj 未知对象
*/
static void testOld(Object obj) {
if (obj instanceof String) {
String s = (String) obj;
if ("模式匹配".equals(s)) {
System.err.println(s);
}
}
} /**
* 新写法
* @param obj 未知对象
*/
static void testNew(Object obj) {
if (obj instanceof String s && "模式匹配".equals(s)) {
System.err.println(s);
}
} public static void main(String[] args) {
testOld("Hello, Java!");
testNew("模式匹配");
}
}
3)、注意

instanceof后面若需要增强判断必须要用&&,不能用||,因为instanceof本来就是做类型匹配的,Java可以确保&&后面的变量一定存在,但无法判断||后面的变量一定存在,所以会报错。

6、record类

1)、说明

Java16新特性,简单讲,就是有了它,声明一个final类变得更简洁和可读。

2)、案例

先来看下写法

/**
* <p>
* JDK16新特性:record类
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 21:52
*/
public record RecordDemo(int type, String typeName) {
private void test() {
System.err.println(type + " | " + typeName);
}
public static void main(String[] args) {
// 这里new的时候带的参数其实就是类的属性,等于声明属性+访问构造方法二合一。
RecordDemo recordDemo = new RecordDemo(100, "葡萄牙");
recordDemo.test();
}
}

上面的新写法等同于下面这种老的写法,一看就懂。

/**
* <p>
* RecordDemo的写法等同于这个类
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 21:55
*/
public final class RecordCustomDemo {
final int type;
final String typeName; public int type() {
return type;
} public String name() {
return typeName;
} public RecordCustomDemo(int type, String typeName) {
this.type = type;
this.typeName = typeName;
} @Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
RecordCustomDemo that = (RecordCustomDemo) o;
return type == that.type && Objects.equals(typeName, that.typeName);
} @Override
public int hashCode() {
return Objects.hash(type, typeName);
}
}
3)、注意

没什么可注意的,就跟使用正常的类差不多,只是自动生成了以下内容:



1)、括号里的参数就是该类的属性,且是final类型;

2)、自动生成一个带有该属性的构造器;

3)、自动生成该属性的访问器,如xx.type()、xx.typeName();

4)、生成了equals和hashCode方法。



如果还是不懂,就理解成lombok中的@Data注解即可,同样的意思。

7、密封类和接口

1)、说明

Java17新特性,密封类和密封接口。

使用sealed关键字声明的类,可以通过设置permits关键字来控制哪些子类可以继承它。

使用sealed关键字声明的接口,可以通过设置permits关键字来控制哪些类可以实现它。。

简单来讲,就是爸爸规定哪个儿子能继承财产。

2)、案例

看下密封类的写法

用sealed声明一个类,设置permits授权哪几个子类可以继承它。

/**
* <p>
* JDK17新特性:密封类
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 17:20
*/
public sealed class Daddy permits Son1, Son2 {
}

第一个儿子可以继承

/**
* <p>
*
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 17:22
*/
public final class Son1 extends Daddy {
}

第二个儿子可以继承

/**
* <p>
*
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 17:23
*/
public final class Son2 extends Daddy {
}

第三个儿子估计是不孝子

可以看到IDEA是有错误提示的,意思是没有被sealed声明的父类所允许。

然后,我们来看看密封接口。

其实和密封类差不多,但还可以结合前面讲过的record来简化代码。

/**
* <p>
* JDK17新特性:密封接口
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 18:03
*/
public sealed interface DaddyInterface permits Son4, Son5 {
void test();
}

第四个儿子可以实现父亲的愿望,用了record之后简化了变量声明及一些内置方法的实现。

/**
* <p>
*
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 17:23
*/
public record Son4(int age, String name) implements DaddyInterface {
@Override
public void test() { }
}

第五个儿子可以实现父亲的愿望

/**
* <p>
*
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/2 17:23
*/
public record Son5(int age, String name) implements DaddyInterface {
@Override
public void test() { }
}

第六个儿子有点傻,不能实现父亲的愿望,可以看到错误提示和前面密封类一样。

3)、注意

1)、sealed声明的父类,它的子类只能用final、sealed、non-sealed来修饰;

2)、sealed声明的父类,至少要有一个子类;

3)、没有在permits中授权的子类,无法继承父类;

4)、密封接口和密封类的注意点没什么区别;

4)、密封接口结合record来完成可以少写更多代码变得更加简洁。



这里特别说一点,sealed和record其实在Java新特性模式匹配中很有意义,但是我认为模式匹配对于从未了解过的Java程序员来讲有些晦涩,结合sealed后有种套娃传销的感觉,如果难于理解就不是我们本来的目的,因此没有专门花费章节赘述,结尾会简单说一下我对模式匹配的看法。

8、switch增强

1)、说明

为什么把switch单独放最后讲,因为Java14-17分别对其做了增强,放在最后汇总起来讲更直观。

一共有三个改变:

1)、支持箭头语法;

2)、支持表达式;

3)、支持case null。

2)、案例

箭头语法,其实就是把旧写法中的冒号和break直接换成了箭头来代替,更简洁。

/**
* <p>
* JDK14新特性:switch箭头语法
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/3 11:05
*/
public class SwitchDemo1 {
private static void foods(int i) {
switch (i) {
case 1:
System.err.println("青椒肉丝");
break;
case 2:
System.err.println("番茄炒蛋");
break;
default:
System.err.println("米饭");
}
} private static void fruits(int i) {
switch (i) {
case 1 -> System.err.println("香蕉");
case 2 -> System.err.println("猕猴桃");
default -> System.err.println("苹果");
}
} public static void main(String[] args) {
foods(1);
fruits(3);
}
}

支持表达式,其实就是能写单个或多个表达式来return。

/**
* <p>
* JDK14新特性:switch支持表达式
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/3 11:05
*/
public class SwitchDemo3 { /**
* 单表达式
*/
private static String fruits(int i) {
return switch (i) {
case 1 -> "香蕉";
case 2 -> "猕猴桃";
default -> "苹果";
};
} /**
* 多表达式
*/
private static String fruitsNew(int i) {
return switch (i) {
case 1, 2 -> {
System.err.println("----------------------------------");
System.err.println("来一个香蕉");
yield "香蕉来咯";
}
case 3, 4 -> {
System.err.println("----------------------------------");
System.err.println("来一个猕猴桃");
yield"猕猴桃来咯";
}
default -> {
System.err.println("----------------------------------");
System.err.println("没的选就来个苹果吧");
yield "苹果来咯";
}
};
} public static void main(String[] args) {
// System.err.println(fruits(2));
// System.err.println(fruits(3)); System.err.println(fruitsNew(2));
System.err.println(fruitsNew(4));
System.err.println(fruitsNew(5));
}
}

支持case null,其实就是case可以接收null值了。

/**
* <p>
* JDK17新特性(预览):switch支持case null
* </p>
*
* @author 程序员济癫,公众号:【Java分享客栈】
* @since 2022/12/3 11:05
*/
public class SwitchDemo2 {
private static void foods(String s) {
if (s == null) {
return;
}
switch (s) {
case "1":
System.err.println("青椒肉丝");
break;
case "2":
System.err.println("番茄炒蛋");
break;
default:
System.err.println("米饭");
}
} private static void fruits(String s) {
switch (s) {
case "1" -> System.err.println("香蕉");
case null -> System.err.println("null");
default -> System.err.println("苹果");
}
} public static void main(String[] args) {
foods("1");
fruits(null);
}
}

可以看下效果,直接传null也不会报错。

3)、注意

1)、箭头语法,冒号和箭头不能同时存在;

2)、表达式,多个表达式时要使用花括号并使用yield关键字返回;

3)、case null是预览功能,在IDEA - Project Structure - Modules中选择Language Level为17(Preview)才能编译通过,参考前面的准备工作。

总结

1)、Java9-17的新特性不仅于此,还有一些挺有特点的内容,比如不可变集合、模块化、String和Stream的API增强等等,但是我个人认为不具有代表性,要么是工具能直接帮你转换,要么就是你大概率用不到,所以就没列出来;



2)、模式匹配,是不少Java程序员关注的内容,本篇中record、switch、密封类和接口的内容其实都是模式匹配的基础,但模式匹配对Java来讲并不成熟,《Thinking In Java》的作者也说过可能要好几年才会看到完整形式的Java模式匹配,所以没必要现在就花太多心思去研究一个残缺版本,这个特性和Python、Kotlin、Scala相比其实还差得远。

Java发展趋势

最后稍微说下不少人关心的这个问题,我觉得只要你了解过Java8之后这些版本的新特性和预览特性,你一定可以发现Java在尝试改变,这是一个很好的信号。



就比如上面的这些新特性,你甚至能找到不少Python、JavaScript等语言的影子,Go语言作为新语言就是站在巨人肩膀上发展起来的,吸纳了很多语言的优秀特点。



现在,Java也在走类似的路,能明显看到它在将一些优秀语言的亮点容纳到自己的新版本中,这种趋势代表着一个意义:Java在不断进步。



网上一直充斥着一些看衰Java的言论,没必要当真,你必须自己去体会生态和了解国内的IT公司动态才能有所感受。



Java依然是国内使用最广泛的语言,并且具备最庞大的生态,这不是一朝一夕可以替代的,是市场规律发展的结果。



SpringBoot3.0支持Java17,Jenkins新版支持Java17,Kafka3.0直接抛弃Java8,还有IDEA2022默认支持Java17,等等之类的开源社区和生态都在给新版的Java背书,更有微软宣布全面拥抱Java,这里面不单单是技术层面的提高,更有利益的诉求和捆绑。



从这一点来说,学习Java完全是值得的,作为一门成熟优秀且严谨的语言,它就像一个白领一样正襟危坐。



我还认为现在学习和掌握Java的工程师,未来转去其他语言也不会有压力,上面的新特性就说明了这种方向,它在吸纳其他语言的亮点。



未来可以预期的是,你转到其他语言会逐渐变的没有那么陌生和晦涩,这是我看到的一个方向,未来的编程语言发展大方向就是大融合(大抄袭,咳咳),你中有我,我中有你。


原创文章纯手打,一个一个字敲出来的,键盘上全是血,如果觉得有帮助麻烦点个推荐吧~

本人致力于分享工作中的经验及趣事,喜欢的话可以进主页关注一下哦~

Java9-17新特性一览,了解少于3个你可能脱节了的更多相关文章

  1. Java9的新特性

    2017.9.21延期了好几次的Java9正式发布,在人工智能的时代,java还能不能持续辉煌是个问题.看看java9的新特性没什么让自己想升级的意愿,因为要么时一些特性用不到,要么时已经有其它方案代 ...

  2. Java单元測试工具JUnit 5新特性一览

    Java单元測试工具JUnit 5新特性一览 作者:chszs,未经博主同意不得转载. 经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs JUnit是最流行的开源 ...

  3. IntelliJ IDEA 16 EAP新特性一览

    IntelliJ IDEA 16 EAP新特性一览 作者:chszs,未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs IntelliJ I ...

  4. (数据科学学习手札111)geopandas 0.9.0重要新特性一览

    本文示例文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 就在几天前,geopandas释放了其最新正式版 ...

  5. (数据科学学习手札129)geopandas 0.10版本重要新特性一览

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 就在前不久,我们非常熟悉的Python地理 ...

  6. c++17 新特性

    编译环境说明:gcc 8.1 + eclipse +windows 10 eclipse cpp默认支持c++14,做c++17开发时,需要手动进行配置. 1.关键字 1)constexpr c++1 ...

  7. Java 17 新特性:switch的模式匹配(Preview)

    还记得Java 16中的instanceof增强吗? 通过下面这个例子再回忆一下: Map<String, Object> data = new HashMap<>(); da ...

  8. (数据科学学习手札139)geopandas 0.11版本重要新特性一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,就在几天前,geopandas ...

  9. C++17 新特性之 std::optional(上)

    最近在学习 c++ 17 的一些新特性,为了加强记忆和理解,把这些内容作为笔记记录下来,有理解不对的地方请指正,欢迎大家留言交流. 引言 在介绍之前,我们从一个问题出发,C++ 的函数如何返回多个值? ...

  10. Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览

    当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...

随机推荐

  1. AQS:Java 中悲观锁的底层实现机制

    介绍 AQS AQS(AbstractQueuedSynchronizer)是 Java 并发包中,实现各种同步组件的基础.比如 各种锁:ReentrantLock.ReadWriteLock.Sta ...

  2. 基于 OpenTelemetry 的链路追踪

    链路追踪的前世今生 分布式跟踪(也称为分布式请求跟踪)是一种用于分析和监控应用程序的方法,尤其是使用微服务架构构建的应用程序.分布式跟踪有助于精确定位故障发生的位置以及导致性能差的原因. 起源 链路追 ...

  3. Elasticsearch: Cerebro 用户界面介绍

  4. 使用KVM的命令行方式安装centos7虚拟机

    前提条件 1.宿主机上已经安装KVM软件,参考网址:https://www.cnblogs.com/sanduzxcvbnm/p/15538881.html 2.已经上传centos7镜像到宿主机里 ...

  5. 2_JDBC

    一. 引言 1.1 如何操作数据库 使用客户端工具访问数据库, 需要手工建立连接, 输入用户名和密码登陆, 编写SQL语句, 点击执行, 查看操作结果(结果集或受行数影响) 1.2 实际开发中, 会采 ...

  6. WPF 的内部世界(控件与布局)

    目录 一.控件与布局 前言 为什么要写WPF呢? 我一开始算是比较抵触WPF的,因为用的人少吗.感觉都是窗体应用能和Winform有什么区别.可是我错了,非常感谢我的讲师,给我推荐刘铁猛的<深入 ...

  7. Centos7下的基本操作

    本系统是在centos7下最小化安装的 文件操作相关 创建文件夹mkdir name //创建一个文件夹 创建文本touch test.txt //创建文本 删除文件夹rm -rf 文件名 //删除文 ...

  8. OpenDataV低代码平台增加自定义属性编辑

    上一篇我们讲到了怎么在OpenDataV中添加自己的组件,为了让大家更快的上手我们的平台,这一次针对自定义属性编辑,我们再来加一篇说明.我们先来看一下OpenDataV中的属性编辑功能. 当我们拖动一 ...

  9. VMware vSphere 8.0 正式版下载

    请访问原文链接:https://sysin.org/blog/vmware-vsphere-8/,查看最新版.原创作品,转载请保留出处. 作者主页:www.sysin.org vSphere 8.0 ...

  10. 2.httprunner-yaml用例结构

    前言: httprunner3.x版本弱化了api层的概念 直接在testcase中写request请求 如果是单个请求,也可以直接写成一个testcase 每个testcase必须具有两个类属性:c ...