JDK更新的新特性
(1)JDK9的新特性:jShell
Java 终于拥有了像Python 和 Scala 之类语言的REPL工具(交互式编程环境,read - evaluate - print - loop):jShell。以交互式的方式对语句和表达式进行求值。即写即得、快速运行。
利用jShell在没有创建类的情况下,在命令行里直接声明变量,计算表达式,执行语句。
(2)异常处理之try-catch资源关闭
JDK7的新特性
①在try后的括号中写入初始化的流对象,可以在执行完try中操作后自动释放流对象
在try的后面可以增加一个(),在括号中可以声明流对象并初始化。try中的代码执行完毕,会自动把流对象释放,就不用写finally了。
格式:
try(资源对象的声明和初始化){
业务逻辑代码,可能会产生异常
}catch(异常类型1 e){
处理异常代码
}catch(异常类型2 e){
处理异常代码
}
说明:
1、在try()中声明的资源,无论是否发生异常,无论是否处理异常,都会自动关闭资源对象,不用手动关闭了。
2、这些资源实现类必须实现AutoCloseable或Closeable接口,实现其中的close()方法。Closeable是AutoCloseable的子接口。Java7几乎把所有的“资源类”(包括文件IO的各种类、JDBC编程的Connection、Statement等接口…)都进行了改写,改写后资源类都实现了AutoCloseable或Closeable接口,并实现了close()方法。
3、写到try()中的资源类的变量默认是final声明的,不能修改。也就是说,不能对try(流对象)中的流对象再次进行赋值修改。
②在try()前实现流对象的声明,在try后的括号中写入已经实现初始化的流对象,执行完try中的操作后,自动释放写入括号中的流资源。
try的前面可以定义流对象,try后面的()中可以直接引用流对象的名称。在try代码执行完毕后,流对象也可以释放掉,也不用写finally了。
格式:
A a = new A();
B b = new B();
try(a;b){
可能产生的异常代码
}catch(异常类名 变量名){
异常处理的逻辑
}
(3)局部变量类型推断
1、局部变量的实例化:
var list = new ArrayList<String>();
var set = new LinkedHashSet<Integer>();
2、增强for循环中的索引:
for (var v : list) {
System.out.println(v);
}
3、传统for循环:
for (var i = 0; i < 100; i++) {
System.out.println(i);
}
4、返回值类型含有复杂的泛型结构:
var iterator = set.iterator();
//Iterator<Map.Entry<Integer, Student>> iterator = set.iterator();
- 不适用场景
- 声明一个成员变量
- 声明一个数组变量,并为数组静态初始化(省略new的情况下)
- 方法的返回值类型
- 方法的参数类型
- 没有初始化的方法内的局部变量声明
- 作为catch块中异常类型
- Lambda表达式中函数式接口的类型
- 方法引用中函数式接口的类型
- var不是一个关键字,而是一个类型名,将它作为变量的类型。不能使用var作为类名。
(4)instanceOf模式匹配
Java 14新特性写法:
if(obj instanceof String str){
.. str.contains(..)..
}else{
...
}
可以在确认对象类型时即实现对于对象的强转,完成强转后的变量声明,简化了代码。
(5)Switch的模式匹配
JDK12中预览特性:
- Java 12将会对switch声明语句进行扩展,使用case L ->来替代以前的break;省去了 break 语句,避免了因少写 break 而出错。
- 同时将多个 case 合并到一行,显得简洁、清晰,也更加优雅的表达逻辑分支。
- 为了保持兼容性,case 条件语句中依然可以使用字符 :
- 但是同一个 switch 结构里不能混用-> 和: ,否则编译错误。
JDK13中二次预览特性:
JDK13中引入了yield语句,用于返回值。这意味着,switch表达式(返回值)应该使用yield,switch语句(不返回值)应该使用break。
yield和return的区别在于:return会直接跳出当前循环或者方法,而yield只会跳出当前switch块。
(6)文本块的使用
在Java中,通常需要使用String类型表达HTML,XML,SQL或JSON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
JDK13的新特性
使用"""作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。因此,文本块将提高Java程序的可读性和可写性。
public class StringTest {
public static void main(String[] args) {
String str = """
hey,my dear
I'll miss you
util the world destroy
util you recall who I am.
""";
System.out.println(str);
}
(7)引用数据类型:record
Record有父类Record,所以不能继承于其他父类
record 是一种全新的类型,它本质上是一个 final 类,同时所有的属性都是 final 修饰,它会自动编译出 public get 、hashcode 、equals、toString、构造器等结构,减少了代码编写量。
当用record 声明一个类时,该类将自动拥有以下功能:
- 获取成员变量的简单方法,注意区别于我们平常getter()的写法。
- 一个 equals 方法的实现,执行比较时会比较该类的所有成员属性。
- 重写 hashCode() 方法。
- 一个可以打印该类所有成员属性的 toString() 方法。
- 只有一个构造方法。
此外:
- 还可以在record声明的类中定义静态字段、静态方法、构造器或实例方法。
- 不能在record声明的类中定义实例字段;类不能声明为abstract;不能声明显式的父类等。(record继承于Record类)
记录不适合哪些场景:
record的设计目标是提供一种将数据建模为数据的好方法。它也不是 JavaBeans 的直接替代品,因为record的方法不符合 JavaBeans 的 get 标准。另外 JavaBeans 通常是可变的,而记录是不可变的。尽管它们的用途有相似之处,但记录并不会以某种方式取代 JavaBean。
(8)密封类
Java 15 引入了 sealed 类,被 sealed 修饰的类可以指定子类。Sealed修饰的类只能被指定的类继承。
具体使用:
- 使用修饰符sealed,可以将一个类声明为密封类。密封的类使用保留关键字permits列出允许继承(即extends)它的子类。
- sealed 修饰的类的机制具有传递性,它的子类必须使用指定的关键字进行修饰,且只能是 final、sealed、non-sealed 三者之一。
- Final修饰的类表示不能被任何类继承。
- non-sealed修饰的类表示可以被任意的子类继承,
- Sealed修饰的类在继承时只能被指定的子类继承
举例:
public abstract sealed class Shape permits Circle, Rectangle, Square { ...}