JDK 的前世今生:细数 -Java5---15- 的那些经典特性,最新“美团 + 字节 + 腾讯”三面问题
(parameters) -> expression 或 (parameters) ->{ statements; }
代码示例:
Arrays.asList("jay", "Eason", "SHE").forEach(( String singer ) -> System.out.print( singer + ",") );
2. 函数式接口
Lambda 的设计者为了让现有的功能与 Lambda 表达式很好兼容,设计出函数式接口。
函数式接口是指只有一个函数的接口,可以隐式转换为 lambada 表达式。
Java 8 提供了注解 @FunctionalInterface,显示声明一个函数式接口。
java.lang.Runnable 和 java.util.concurrent.Callable 是函数式接口的例子~
@FunctionalInterfacepublic interface Runnable {public abstract void run();}
3. 方法引用
方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实例)的方法或构造器。它与 Lambda 表达式配合使用,可以减少冗余代码,使代码更加简洁。
//利用函数式接口 Consumer 的 accept 方法实现打印,Lambda 表达式如下 Consumer<String> consumer = x -> System.out.println(x);consumer.accept("jay");//引用 PrintStream 类(也就是 System.out 的类型)的 println 方法,这就是方法引用 consumer = System.out::println;consumer.accept("私信资料,领一线大厂面试专题");
4. 默认方法
默认方法就是一个在接口里面有了一个实现的方法。它允许将新方法添加到接口,但不强制实现了该接口的类必须实现新的方法。
public interface ISingerService {// 默认方法 default void sing(){System.out.println("唱歌");}void writeSong();}
//JaySingerServiceImpl 不用强制实现 ISingerService 的默认 sing()方法 public class JaySingerServiceImpl implements ISingerService {@Overridepublic void writeSong() {System.out.println("写了一首七里香");}}
5.Stream API
Stream API,支持对元素流进行函数式操作,它集成在 Collections API 中,可以对集合进行批量操作。常用 API:
filter 筛选
map 流映射
reduce 将流中的元素组合起来
collect 返回集合
sorted 排序
flatMap 流转换
limit 返回指定流个数
distinct 去除重复元素
public class Singer {
private String name;private Integer songNum;private Integer age;...}
List<Singer> singerList = new ArrayList<Singer>();singerList.add(new Singer("jay", 11, 36));singerList.add(new Singer("eason", 8, 31));singerList.add(new Singer("JJ", 6, 29));
List<String> singerNameList = singerList.stream().filter(singer -> singer.getAge() > 30) //筛选年龄大于 30.sorted(Comparator.comparing(Singer::getSongNum)) //根据歌曲数量排序.map(Singer::getName) //提取歌手名字.collect(Collectors.toList()); //转换为 List
6. Optional
Java 8 引入 Optional 类,用来解决 NullPointerException。Optional 代替 if...else 解决空指针问题,使代码更加简洁。
if...else 判空
Singer singer = getSingerById("666");if (singer != null) {String name = singer.getName();System.out.println(name);}
Optional 的判空
Optional<Singer> singer = Optional.ofNullable(getSingerById("666"));singer.ifPresent(s -> System.out.println(s.getName()));
7. Date Time API
JDK 8 之前的日期 API 处理存在非线程安全、时区处理麻烦等问题。Java 8 在 java.time 包下提供了新的日期 API,简化了日期的处理~
LocalDate today = LocalDate.now();int year = today.getYear();System.out.println("今年是" + year);//是否闰年 System.out.println("今年是不是闰年:" + today.isLeapYear());
LocalDateTime todayTime = LocalDateTime.now();System.out.println("当前时间" + todayTime);//时区指定 System.out.println("美国时间:" + ZonedDateTime.of(todayTime,ZoneId.of("America/Los_Angeles")));
LocalDate specailDate = LocalDate.of(2020, 6, 20);LocalDate expectDate = specailDate.plus(100, ChronoUnit.DAYS);System.out.println("比较特别的一天" + specailDate);System.out.println("特殊日期的 100 天" + expectDate);
8. 重复注解
重复注解,即一个注解可以在一个类、属性或者方法上同时使用多次;用 @Repeatable 定义重复注解
@Repeatable(ScheduleTimes.class)public @interface ScheduleTime {String value();}
public @interface ScheduleTimes {ScheduleTime[] value();}
public class ScheduleTimeTask {@ScheduleTime("10")@ScheduleTime("12")public void doSomething() { }}
9. Base64
Java 8 把 Base64 编码的支持加入到官方库中~
String str = "私信资料,领一线大厂面试专题";String encoded = Base64.getEncoder().encodeToString(str.getBytes( StandardCharsets.UTF_8));String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
10. JVM 的新特性
使用元空间 Metaspace 代替持久代(PermGen space),JVM 参数使用-XX:MetaSpaceSize 和-XX:MaxMetaspaceSize 设置大小。
Java 9 新特性
![](https://static001.geekbang.org/infoq/0d/0d8dda75a1609e556ffe60c398e03eed.png)
1. java 模块系统
什么是模块化?
?
一个大型系统,比如一个商城网站,它会包含很多模块的,如:订单模块,用户信息模块,商品信息模块,广告位模块等等。各个模块之间会相互调用。如果每个模块单独运行都会带动其他所有模块,性能非常低效。但是,如果某一模块运行时,只会启动它所依赖的模块,性能大大提升。这就是 JDK 9 模块化的思想。
?
什么是 JDK 9 模块化?
?
Java 平台模块系统,即 Project Jigsaw,把模块化开发实践引入到了 Java 平台中。在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。
?
Java 9 模块的重要特征:
?
在其工件(artifact)的根目录中包含了一个描述模块的 module-info.class 文 件。
工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。
这个文件由根目录中的源代码文件 module-info.java 编译而来。
该模块声明文件可以描述模块的不同特征。
?
在 module-info.java 文件中,我们可以用新的关键词 module 来声明一个模块,如下所示。下面给出了一个模块 com.mycompany.mymodule 的最基本的模块声明
module com.jay.sample { //关键词 module 来声明一个模块 exports com.jay.sample; //使用 exports 可以声明模块对其他模块所导出的包。requires com.jay.common; //使用 requires 可以声明模块对其他模块的依赖关系。}
2. 不可变集合工厂方法
为了创建不可变集合,JDK9 之前酱紫的:
List<String> stringList = new ArrayList<>();stringList.add("私信资料:");stringList.add("领一线大厂面试专题");List<String> unmodifiableList = Collections.unmodifiableList(stringList);
JDK 9 提供了 List.of()、Set.of()、Map.of()和 Map.ofEntries()等工厂方法来创建不可变集合:
List<String> unmodifiableList = List.of("私信资料:","领一线大厂面试专题");
3. 接口支持私有方法
JDK 8 支持在接口实现默认方法和静态方法,但是不能在接口中创建私有方法,为了避免了代码冗余和提高阅读性,JDK 9 在接口中支持私有方法。
public interface IPrivateInterfaceTest {
//JDK 7 之前 String a = "jay";void method7();
//JDK 8default void methodDefault8(){System.out.println("JDK 8 新特性默认方法");}static void methodStatic8() {System.out.println("JDk 8 新特性静态方法");}
//Java 9 接口支持私有方法 private void method9(){}}
4. ?钻石操作符升级
钻石操作符是在 java 7 中引入的,可以让代码更易读,但它不能用于匿名的内部类。
在 java 9 中, 它可以与匿名的内部类一起使用,从而提高代码的可读性。
//JDK 5,6Map<String, String> map56 = new HashMap<String,String>();//JDk 7,8Map<String, String> map78 = new HashMap<>();//JDK 9 结合匿名内部类的实现 Map<String, String> map9 = new HashMap<>(){};
5. Optional 类改进
java 9 中,java.util.Optional 添加了很多新的有用方法,如:
stream()
ifPresentOrElse()
or()
ifPresentOrElse 方法的改进就是有了 else,接受两个参数 Consumer 和 Runnable。
import java.util.Optional;
public class OptionalTest {public static void main(String[] args) {Optional<Integer> optional = Optional.of(1);
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->System.out.println("Not Present."));
optional = Optional.empty();
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->System.out.println("Not Present."));}
}
6. 多版本兼容 Jar 包
?
很多公司使用的 JDK 都是老版本的,JDK6、JDk5 ,甚至 JDk4 的,不是他们不想升级 JDk 版本,而是担心兼容性问题。JDK 9 的一个新特性,多版本兼容 Jar 包解决了这个问题。举个例子:假设你一直用的是小米 8,已经非常习惯它的运行流程了,突然出来小米 9,即使小米 9 很多新功能引人入胜,但是有些人不会轻易买小米 9,因为已经已经习惯小米 8 的流程。同理,为什么很多公司不升级 JDK,就是在此。但是呢,JDK 9 的这个功能很强大,它可以让你的版本升级到 JDK 9,但是还是老版本的运行流程,即在老的运行流程继承新的功能~
?
7. JShell 工具
jShell 工具相当于 cmd 工具,然后呢,你可以像在 cmd 工具操作一样,直接在上面运行 Java 方法,Java 语句等~
jshell> System.out.println("私信资料,领一线大厂面试专题");私信资料,领一线大厂面试专题
8. try-with-resources 的改进
JDK 9 对 try-with-resources 异常处理机制进行了升级~
//JDK 7,8try (BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")) {br.readLine();}catch(IOException e){log.error("IO 异常,e:{}",e);}//JDk 9BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")try(br){br.readLine();}catch(IOException e){log.error("IO 异常,e:{}",e);}
9. Stream API 的改进
JDK 9 为 Stream API 引入以下这些方法,丰富了流处理操作:
takeWhile()
dropWhile()
iterate
ofNullable
「takeWhile」
使用一个断言(Predicate 接口)作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false
// 语法格式 default Stream<T> takeWhile(Predicate<? super T> predicate)//代码示例 Stream.of(1,2,3).takeWhile(s-> x<2).forEach(System.out::println);//输出 1
「dropWhile」
与 takeWhile()作用相反,使用一个断言(Predicate 接口)作为参数,直到断言语句第一次返回 true,返回给定 Stream 的子集
//语法 default Stream<T> dropWhile(Predicate<? super T> predicate)//代码示例 Stream.of(1,2,3).dropWhile(s-> x<2).forEach(System.out::println);//输出 23
「iterate」
iterate() 方法能够返回以 seed(第一个参数)开头,匹配 Predicate(第二个参数)直到返回 false,并使用第三个参数生成下一个元素的元素流。
//语法 static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)//代码示例 IntStream.iterate(2, x -> x < 10, x -> x*x).forEach(System.out::println);//输出 24
「ofNullable」
如果指定元素为非 null,则获取一个元素并生成单个元素流,元素为 null 则返回一个空 Stream。
//语法 static <T> Stream<T> ofNullable(T t)//代码示例 Stream<Integer> s1= Stream.ofNullable(100);s1.forEach(System.out::println)Stream<Integer> s2 = Stream.ofNullable(null);s2.forEach(System.out::println)//输出 100
10.其他
?
HTTP 2 客户端 (支持 WebSocket 和 HTTP2 流以及服务器推送)
进程 API(控制和管理操作系统进程)
String 底层存储结构更改(char[]替换为 byte[])
标识符添加限制( String _ ="hello"不能用)
响应式流 API (支持 Java 9 中的响应式编程)
?
Java 10 新特性
![](https://static001.geekbang.org/infoq/93/93e7368246bd48a7520e576868f842fc.png)
1.局部变量类型推断
JDK 10 增加了局部变量类型推断(Local-Variable Type Inference)功能,让 Java 可以像 Js 里的 var 一样可以自动推断数据类型。Java 中的 var 是一个保留类型名称,而不是关键字。
JDK 10 之前
List<String> list = new ArrayList<String>();Stream<Integer> stream = Stream.of(1, 2, 3);
JDK 10 之后
var list = new ArrayList<String>(); // ArrayList<String>var stream = Stream.of(1, 2, 3);
var 变量类型推断的使用也有局限性,仅**「局限」**于以下场景:
具有初始化器的局部变量
增强型 for 循环中的索引变量
传统 for 循环中声明的局部变量
而**「不能用于」**
推断方法的参数类型
构造函数参数类型推断
推断方法返回类型
字段类型推断
捕获表达式
2. 不可变集合的改进
JDK 10 中,List,Set,Map 提供了一个新的静态方法 copyOf(Collection<? extends E> coll),它返回 Collection 集合一个不可修改的副本。
JDK 源码:
static <E> List<E> copyOf(Collection<? extends E> coll) {return ImmutableCollections.listCopy(coll);}
使用实例:
var oldList = new ArrayList<String>();oldList.add("私信资料:");oldList.add("");
var copyList = List.copyOf(oldList);oldList.add("收藏、转载、点赞三连");copyList.add("双击 666"); //UnsupportedOperationException 异常
3. 并行全垃圾回收器 G1
?
JDK 9 引入 G1 作为默认垃圾收集器,执行 GC 时采用的是基于单线程标记扫描压缩算法(mark-sweep-compact)。为了最大限度地减少 Full GC 造成的应用停顿的影响,Java 10 中将为 G1 引入多线程并行 GC,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。
?
4. 线程本地握手
Java 10 中线程管控引入 JVM 安全点的概念,将允许在不运行全局 JVM 安全点的情况下实现线程回调,由线程本身或者 JVM 线程来执行,同时保持线程处于阻塞状态,这将会很方便使得停止单个线程或不停止线程成为可能。
5. Optional 新增 orElseThrow()方法
Optional、OptionalDouble 等类新增一个方法 orElseThrow(),在没有值时抛出异常
6. 其他新特性
基于 Java 的 实验性 JIT 编译器
类数据共享
Unicode 语言标签扩展
根证书
基于时间(Time-Based)的版本控制模型
Java 11 新特性
![](https://static001.geekbang.org/infoq/ed/ed9db8d8be24d3ba64d83b747c80a763.png)
1.字符串操作
String 类是 Java 最常用的类,JDK 11 增加了一系列好用的字符串处理方法
isBlank() 判空。
strip() 去除首尾空格
stripLeading() 去除字符串首部空格
stripTrailing() 去除字符串尾部空格
lines() 分割获取字符串流。
repeat() 复制字符串
// 判断字符串是否为空白" ".isBlank(); // true
// 去除首尾空格" jay ".strip(); // "jay"
// 去除首部空格" jay ".stripLeading(); // "jay "
去除字符串尾部空格" jay ".stripLeading(); // " jay"
// 行数统计"a\nb\nc".lines().count(); // 3
// 复制字符串"jay".repeat(3); // "jayjayjay"
2.用于 Lambda 参数的局部变量语法
局部变量类型推断是 Java 10 引入的新特性,但是不能在 Lambda 表达式中使用。Java 11 再次创新,它允许开发者在 Lambda 表达式中使用 var 进行参数声明。
var map = new HashMap<String, Object>();map.put("私信资料", "领一线大厂面试专题");map.forEach((var k, var v) -> {System.out.println(k + ": " + v);});
3.标准化 HTTP Client
Java 9 引入 Http Client API,Java 10 对它更新,Java 11 对它进行标准化。这几个版本后,Http Client 几乎被完全重写,支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets。
HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://github.com/whx123/JavaHome")).GET().build();
// 同步 HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.body());
// 异步 client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body).thenAccept(System.out::println);
4. 单个命令编译运行源代码
Java 11 增强了 Java 启动器,使之能够运行单一文件的 Java 源代码。
Java 11 之前,要运行一个 Java 源代码必须先编译,再运行
// 编译 javac Jay.java// 运行 java Jay
Java 11 之后,只要一个 java 命令就搞定
java Jay.java
5. ZGC:可伸缩低延迟垃圾收集器
ZGC ,即 Z Garbage Collector(垃圾收集器或垃圾回收器)。它是一个可伸缩的、低延迟的垃圾收集器。 ZGC 主要为了满足如下目标进行设计:
GC 停顿时间不超过 10ms
既能处理几百 MB 的小堆,也能处理几个 TB 的大堆
应用吞吐能力不会下降超过 15%(与 G1 回收算法相比)
方便在此基础上引入新的 GC 特性和利用 colord
针以及 Load barriers 优化奠定基础
当前只支持 Linux/x64 位平台
6.其他一些特性
添加 Epsilon 垃圾收集器。
支持 TLS 1.3 协议
飞行记录器分析工具
动态类文件常量
低开销的 Heap Profiling
Java 12 新特性
![](https://static001.geekbang.org/infoq/e0/e06ee2870b6dee3d1f1f7a18b08e6f41.png)
1. Switch 表达式扩展(预览功能)
传统的 switch 语句,容易漏写 break 而出错,同时写法并不简洁优雅。
Java 12 之前
switch (day) {case MONDAY:case FRIDAY:case SUNDAY:System.out.println(6);break;case TUESDAY:System.out.println(7);break;case THURSDAY:case SATURDAY:System.out.println(8);break;case WEDNESDAY:System.out.println(9);break;}
JDk 12 之后,Switch 表达式得到增强,能接受语句和表达式。
switch (day) {case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);case TUESDAY -> System.out.println(7);case THURSDAY, SATURDAY -> System.out.println(8);case WEDNESDAY -> System.out.println(9);}
2. 紧凑的数据格式
JDK 12 新增了 NumberFormat 对复杂数字的格式化
NumberFormat numberFormat = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);System.out.println(numberFormat.format(100000));//output10 万
3. 字符串支持 transform、indent 操作
transform 字符串转换,可以配合函数式接口 Function 一起使用
List<String> list1 = List.of("jay", " 私信资料,领一线大厂面试专题");List<String> list2 = new ArrayList<>();list1.forEach(element ->list2.add(element.transform(String::strip).transform((e) -> "Hello," + e)));list2.forEach(System.out::println);//输出 Hello,jayHello,私信资料,领一线大厂面试专题
indent 缩进,每行开头增加空格 space 和移除空格
String result = "Java\n Python\nC".indent(3);System.out.println(result);//输出 JavaPythonC
4. Files.mismatch(Path, Path)
Java 12 新增了 mismatch 方法,此方法返回第一个不匹配的位置,如果没有不匹配,则返回 -1L。
public static long mismatch(Path path, Path path2) throws IOException;
代码示例:
Path file1 = Paths.get("c:\jay.txt");Path file2 = Paths.get("c:\私信资料领一线大厂面试专题.txt");
try {long fileMismatch = Files.mismatch(file1, file2);System.out.println(fileMismatch);} catch (IOException e) {e.printStackTrace();}
5. Teeing Collector
Teeing Collector 是 Streams API 中引入的新的收集器实用程序,它的作用是 merge 两个 collector 的结果,API 格式如下:
public static <T, R1, R2, R>Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,Collector<? super T, ?, R2> downstream2,BiFunction<? super R1, ? super R2, R> merger)
直接看代码例子吧,如下为求学生的平均分和总分的例子
List<Student> studentList= Arrays.asList(new Student("jay", 90),new Student("私信资料,领一线大厂面试专题", 100),new Student("私信资料,领一线大厂面试专题", 80));String teeingResult=studentList.stream().collect(Collectors.teeing(Collectors.averagingInt(Student::getScore),Collectors.summingInt(Student::getScore),(s1,s2)-> s1+ ":"+ s2));System.out.println(teeingResult); //90:270
6.其他特性
支持 unicode 11(684 个新字符、11 个新 blocks、7 个新脚本)
JVM 常量 API (主要在新的 java.lang.invoke.constant 包中定义了一系列基于值的符号引用类型,能够描述每种可加载常量。)
Shenandoah GC(低暂停时间垃圾收集器)
G1 收集器提升 (可中止的混合收集集合、及时返回未使用的已分配内存)
默认 CDS 档案
JMH 基准测试
Java 13 新特性
![](https://static001.geekbang.org/infoq/ee/ee74922fbd9015e77cca527a7f93481f.png)
Switch 表达式扩展(引入 yield 关键字)
传统的 switch:
private static String getText(int number) {String result = "";switch (number) {case 1, 2:result = "one or two";break;case 3:result = "three";break;case 4, 5, 6:result = "four or five or six";break;default:result = "unknown";break;
Java 13 之后,value break 语句不再被编译,而是用 yield 来进行值返回
private static String getText(int number) {return switch (number) {case 1, 2:yield "one or two";case 3:yield "three";case 4, 5, 6:yield "four or five or six";default:yield "unknown";};}
2.文本块升级
Java 13 之前,字符串不能够多行使用,需要通过换行转义或者换行连接符等等,反正就是好麻烦、好难维护。
String html = "<html>\n" +" <body>\n" +" <p>Hello, 私信资料,领一线大厂面试专题</p>\n" +" </body>\n" +"</html>\n";
Java 13 之后,清爽多了~
String html = """<html><body><p>Hello, 私信资料,领一线大厂面试专题</p></body></html>""";
3. SocketAPI 重构
传统的 Java Socket API(java.net.ServerSocket 和 java.net.Socket)依赖于 SocketImpl 的内部实现
在 Java 13 之前,通过使用 PlainSocketImpl 作为 SocketImpl 的具体实现。
Java 13 中的新底层实现,引入 NioSocketImpl 的实现用以替换 SocketImpl 的 PlainSocketImpl 实现,此实现与 NIO(新 I/O)实现共享相同的内部基础结构,并且与现有的缓冲区高速缓存机制集成在一起。
一个 Socket 简单例子:
import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;
public class SocketAPITest {public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(8080)){boolean runFlag = true;while(runFlag){Socket clientSocket = serverSocket.accept();//搞事情}} catch (IOException e) {e.printStackTrace();}}}
运行以上的实例,看下是否有以下关键词输出~
[class,load] sun.nio.ch.NioSocketImpl
4.FileSystems.newFileSystem 新方法
FileSystems 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序:
1、newFileSystem(Path)
2、newFileSystem(Path, Map<String, ?>)
3、newFileSystem(Path, Map
<String, ?>, ClassLoader)
5. 增强 ZGC 释放未使用内存
ZGC 是 Java 11 中引入的最为瞩目的垃圾回收特性,是一种可伸缩、低延迟的垃圾收集器。但是实际使用中,它不能够主动将未使用的内存释放给操作系统。
Java 13 中对 ZGC 的改进,包括释放未使用内存给操作系统、支持最大堆大小为 16TB、JVM 参数-XX:SoftMaxHeapSize 来软限制堆大小
6.其他特性
动态 CDS 存档, 扩展了 Java 10 中引入的类数据共享功能, 使用 CDS 存档变得更容易。
文本块的字符串类新方法,如 formatted(Object…args),stripIndent()等。
Java 14 新特性
![](https://static001.geekbang.org/infoq/8e/8e4f5c6757ae07573020f4509db12559.png)
1. instanceof 模式匹配
instanceof 传统使用方式:
if (person instanceof Singer) {Singer singer = (Singer) person;singer.sing();} else if (person instanceof Writer) {Writer writer = (Writer) person;writer.write();}
Java 14 对 instanceof 进行模式匹配改进之后
if (person instanceof Singer singer) {singer.sing();} else if (person instanceof Writer writer) {writer.write();}
2.Record 类型(预览功能)
Java 14 将 Record 类型作为预览特性而引入,有点类似于 Lombok 的 @Data 注解,看个例子吧:
public record Person(String name, int age) {public static String address;
public String getName() {return name;}}
反编译结果:
public final class Person extends java.lang.Record {private final java.lang.String name;private final java.lang.String age;
public Person(java.lang.String name, java.lang.String age) { /* compiled code */ }
public java.lang.String getName() { /* compiled code */ }
public java.lang.String toString() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public java.lang.String name() { /* compiled code */ }
public java.lang.String age() { /* compiled code */ }}
可以发现,当用 Record 来声明一个类时,该类将自动拥有下面特征:
构造方法
hashCode() 方法
euqals() 方法
toString() 方法
类对象被 final 关键字修饰,不能被继承。
3. Switch 表达式-标准化
switch 表达式在之前的 Java 12 和 Java 13 中都是处于预览阶段,终于在 Java 14 标准化,成为稳定版本。
Java 12 为 switch 表达式引入 Lambda 语法
Java 13 使用 yield 代替 break 关键字来返回表达式的返回值。
String result = switch (day) {case "M", "W", "F" -> "MWF";case "T", "TH", "S" -> "TTS";default -> {if (day.isEmpty()) {yield "Please insert a valid day.";} else {yield "Looks like a Sunday.";}}};System.out.println(result);
4. 改进 NullPointerExceptions 提示信息
Java 14 之前:
String name = song.getSinger().getSingerName()
//堆栈信息
评论