直接上干货。
jdk14的安装和新版idea的安装就不说了,下面奉上两个软件。
链接:https://pan.baidu.com/s/1eBd6fmlkK5qF5ulJM9HJfw 提取码:vst7
安装完成之后如下:2020年3月17发布的
idea还有几个小设置:
ok,设置完毕,直接进入正题。
总共:5个语法改变,3个虚拟机优化,详细介绍往下看。语法层面优化总共五处。以下的预览代表还未正式确认,让使用者提意见的。
语法一:instanceof的模式匹配(预览) 什么意思?一脸懵逼??直接上代码:
public class Feature01 {
@Test
public void test1(){
Object obj = new String("hello,Java14");
//jdk14之前的写法
if(obj instanceof String){
String str = (String) obj;
System.out.println(str.contains("Java"));
}else{
System.out.println("非String类型");
}
//举例1:
//新特性:省去了强制类型转换的过程,但是此时的str作用域只限于if内
if(obj instanceof String str){
System.out.println(str.contains("Java"));
}else{
System.out.println("非String类型");
}
}
}
实际上就是之前的两行代码,判断+强转 变成了一句代码。
//之前
if(obj instanceof String){
String str = (String) obj;
System.out.println(str.contains("Java"));
}
//jdk14
if(obj instanceof String str){
System.out.println(str.contains("Java"));
}
注意:jdk14里面 此时的str的作用域仅限于if结构内
再看下一个例子:
//举例2:
class Monitor{
private String model;
private double price;
//复杂写法
public boolean equals(Object o){
if(o instanceof Monitor other){
if(model.equals(other.model) && price == other.price){
return true;
}
}
return false;
}
//简单写法
public boolean equalsSimple(Object o){
return o instanceof Monitor other && model.equals(other.model) && price == other.price;
}
}
语法二:非常实用的NullPointerException
大白话来说就是 提示空指针异常的地方变得更具体,更准确了。代码如下:
简介一下如下代码:
Bank类有个私有属性Customer类,Customer类中有个私有属性Account类,Account中有个withdraw(double amt)的方法。
public class Feature02 {
public static void main(String[] args) {
//这样是不会报错的
// Bank bank = new Bank(new Customer(new Account(1000)));
//但是这样就会报错了,因为Customer类的私有属性 Account没有被new出来,直接调用withdraw方法,空指针
Bank bank = new Bank(new Customer());
//但是这样就会报错了,因为Customer类的私有属性 Account没有被new出来,直接调用withdraw方法,空指针
bank.getCustomer().getAccount().withdraw(200);
}
}
class Bank {
private Customer customer;
public Bank() {
}
public Bank(Customer customer) {
this.customer = customer;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
class Customer {
private Account account;
public Customer() {
}
public Customer(Account account) {
this.account = account;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
class Account {
private double balance;//余额
public Account() {
}
public Account(double balance) {
this.balance = balance;
}
//取钱操作
public void withdraw(double amt) {
if (balance >= amt) {
balance -= amt;
System.out.println("成功取款:" + amt);
} else {
System.out.println("余额不足,取款失败");
}
}
}
以前的报错大家很熟悉,普通空指针。如下
但是jdk14,有个虚拟机参数如下:
-XX:+ShowCodeDetailsInExceptionMessages
我们设置一下这个参数,再来看看结果
运行结果:
直接贴出来吧:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.herman.feature.Account.withdraw(double)" because the return value of "com.herman.feature.Customer.getAccount()" is null
可以清楚的看出是 "com.herman.feature.Customer.getAccount()" is null报错,这就很nice。。
语法三:Record(预览特性)
神说要用record,于是就有了 。什么意思??直接上代码吧。感觉这个 局限性有点高,可能开发用的不多。
之前我们用的lombok插件,就是为了解决实体/bean中的get set方法,构造器,toString,equals等服务的,这次新增了Record。
我们以前写实体,一般写法如下:属性然后 get set toString equals 写一堆。
多注意这里的final修饰。record反编译之后,属性都被final修饰了。
看着很是麻烦重复,jdk14引入新写法如下:
public record Person(String name,Person partner) {
}
??完了?就这么简单? 没错 就这么简单。
测试代码如下:
public class Feature03 {
@Test
public void test1(){
//测试构造器
Person p1 = new Person("罗密欧",new Person("zhuliye",null));
//测试toString()
System.out.println(p1);
//测试equals():
Person p2 = new Person("罗密欧",new Person("zhuliye",null));
System.out.println(p1.equals(p2));
//测试hashCode()和equals()
HashSet set = new HashSet();
set.add(p1);
set.add(p2);
for (Person person : set) {
System.out.println(person);
}
//测试name()和partner():类似于getName()和getPartner()
System.out.println(p1.name());
System.out.println(p1.partner());
}
}
运行结果:
很吊,但是刚才为什么说有局限性呢,来看。
优点:还可以声明静态的属性、静态的方法、构造器、实例方法
局限1:record中不可以声明非静态的属性
局限2:不可以将record定义的类声明为abstract的
局限2:不可以给record定义的类声明显式的父类(非Record类)
下面的写法都是报错的:
具体原因我们看idea反编译之后的.class文件吧。原因一目了然
语法四:switch表达式
这是JDK 12和JDK 13中的预览特性,现在是正式特性了。
该特性规定,switch可以当作语句使用,也可以当作表达式使用。
具体情况:
使用->来替代以前的:+break;另外还提供了yield来在block中返回值
上代码:
/**
* switch的新特性
*/
public class Feature04 {
//jdk12之前的用法
@Test
public void test1() {
Week day = Week.FRIDAY;
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
System.out.println(1);
break;
case THURSDAY:
System.out.println(2);
break;
case FRIDAY:
case SATURDAY:
System.out.println(3);
break;
case SUNDAY:
System.out.println(4);
break;
default:
throw new IllegalStateException("What day is today?" + day);
}
}
//jdk12新特性:引用switch表达式
@Test
public void test2(){
Week day = Week.FRIDAY;
switch (day){
case MONDAY,TUESDAY,WEDNESDAY -> System.out.println(1);
case THURSDAY -> System.out.println(2);
case FRIDAY,SATURDAY -> System.out.println(3);
case SUNDAY -> System.out.println(4);
default -> throw new IllegalStateException("What day is today?" + day);
}
//使用变量接收switch表达式的值
int num = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY -> 1;
case THURSDAY -> 2;
case FRIDAY, SATURDAY -> 3;
case SUNDAY -> 4;
default -> throw new IllegalStateException("What day is today?" + day);
};
System.out.println(num);
}
//jdk13新特性:引用了yield关键字,用于返回指定的数据,结束switch结构
@Test
public void test3(){
String x = "3";
int num = switch (x){
case "1" -> 1;
case "2" -> 2;
case "3" -> 3;
default -> {
System.out.println("default...");
yield 4;
}
};
System.out.println(x);
}
@Test
public void test4(){
String x = "3";
int num = switch (x){
case "1":yield 1;
case "2":yield 2;
case "3":yield 3;
default: yield 4;
};
System.out.println(num);
}
}
enum Week {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
总结:
语法五:文本块(预览第二版)
什么意思?就是拼接各种字符串的时候以前是那样的,现在是这样的。哈哈
可能之前在java里面拼接html或者邮件格式等,显得格式很难看,换行什么的,不好看,现在修改了一下。看代码吧。
/**
* 文本块(text blocks)的使用
*/
public class Feature05 {
@Test
public void test1(){
//以前写法,格式是不是很不好看?
String text1 = "The Sound of silence\n" +
"Hello darkness, my old friend\n" +
"I've come to talk with you again\n" +
"Because a vision softly creeping\n" +
"Left its seeds while I was sleeping\n" +
"And the vision that was planted in my brain\n" +
"Still remains\n" +
"Within the sound of silence";
System.out.println(text1);
//jdk13中的新特性:
String text2 = """
The Sound of silence
Hello darkness, my old friend
I've come to talk with you again
Because a vision softly creeping
Left its seeds while I was sleeping
And the vision that was planted in my brain
Still remains
Within the sound of silence""";
//注意:“”“ 放在下一行和放在上一行,text1和text2长度不一样,text2长度 变长 一位
//""";
System.out.println();
System.out.println(text2);
}
//html
@Test
public void test2(){
//以前写法,格式是不是很不好看?
String html1 = "\n" +
"\n" +
" \n" +
" java14新特性 \n" +
"\n" +
"\n" +
" hello,atguigu
\n" +
"\n" +
"";
//jdk13中的新特性:
String html2 = """
java14新特性
hello,atguigu
""";
}
//json
@Test
public void test3() {
//jdk13之前的写法
String myJson = "{\n" +
" \"name\":\"Song Hongkang\",\n" +
" \"address\":\"www.atguigu.com\",\n" +
" \"email\":\"shkstart@126.com\"\n" +
"}";
System.out.println(myJson);
//jdk13的新特性
String myJson1 = """
{
"name":"Song Hongkang",
"address":"www.atguigu.com",
"email":"shkstart@126.com"
}""";
System.out.println(myJson1);
}
//sql
@Test
public void test4(){
//以前写法,格式是不是很不好看?
String sql = "SELECT id,NAME,email\n" +
"FROM customers\n" +
"WHERE id > 4\n" +
"ORDER BY email DESC";
//jdk13新特性:
String sql1 = """
SELECT id,NAME,email
FROM customers
WHERE id > 4
ORDER BY email DESC
""";
}
//jdk14新特性
@Test
public void test5(){
String sql1 = """
SELECT id,NAME,email
FROM customers
WHERE id > 4
ORDER BY email DESC
""";
System.out.println(sql1);
// \:取消换行操作
// \s:表示一个空格
String sql2 = """
SELECT id,NAME,email \
FROM customers\s\
WHERE id > 4 \
ORDER BY email DESC
""";
System.out.println(sql2);
}
}
总结:用 """ 文本 """ 来搞这个字符串,显得格式不错。
语法层面就上面这些。
下面看一下jvm层面的优化。(了解)
1.弃用ParallelScavenge和SerialOld GC组合
2.删除CMS垃圾回收器
3.我们还看到了引入了两个新的收集器:
ZGC (JDK11出现)和Shenandoah(非oracle出品)
ZGC:以低延迟为首要目标的一款垃圾收集器。设置ZGC命令:-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
Shenandoah 这哥们 不是oracle团队出品,估计也活不久。
神一样的cms,还是被删除淘汰了。
还有一些其他的改动,就不一一列出了,平时基本用不到。
写在最后:JDK 14 性能提升,但 JDK 8 仍是最强王者!
感谢尚硅谷!硅谷无敌!
原创不易,转载请注明出处。
作者:掌心一点微笑