
文章主要介绍了JDK11-17新版本的主要特性
JDK12
升级的switch语句
在jdk12之前的switch语句中,如果没有写break,则会出现case穿透现象,下面是对case穿透的一个应用,根据输入的月份打印相应的季节。
int month = 3;
switch (month) {
case 3:
case 4:
case 5:
System.out.println("spring");
break;
case 6:
case 7:
case 8:
System.out.println("summer");
break;
case 9:
case 10:
case 11:
System.out.println("autumn");
break;
case 12:
case 1:
case 2:
System.out.println("winter");
break;
default:
System.out.println("wrong");
break;
}
在jdk12之后我们可以省略全部的break和部分case,这样使用
int month = 3;
switch (month) {
case 3,4,5 -> System.out.println("spring");
case 6,7,8 -> System.out.println("summer");
case 9,10,11 -> System.out.println("autumn");
case 12, 1,2 -> System.out.println("winter");
default -> System.out.println("wrong");
}
这个是预览功能,如果需要编译和运行的话需要使用下面命令,预览功能在2个版本之后会成为正式版,即如果你使用的是jdk14以上的版本,正常的编译和运行即可。否则需要使用预览功能来编译和运行
编译:
javac --enable-preview -source 12 Test.java
运行:
java --enable-preview Test
JDK13
升级的switch语句
jdk13中对switch语句又进行了升级,可以switch的获取返回值
示例:
int month = 3;
String result = switch (month) {
case 3,4,5 -> "spring";
case 6,7,8 -> "summer";
case 9,10,11 -> "autumn";
case 12, 1,2 -> "winter";
default -> "wrong";
};
System.out.println(result);
对于jdk15之后的版本可以直接编译和运行,否则需要使用下面命令执行该预览功能
编译:
javac --enable-preview -source 13 Test.java
运行:
java --enable-preview Test
文本块的变化
在jdk13之前的版本中如果输入的字符串中有换行的话,需要添加换行符
String s = "Hello\nWorld\nLearn\nJava";
System.out.println(s);
jdk13之后可以直接这样写:
String s = """
Hello
World
Learn
Java
""";
System.out.println(s);
这样的字符串更加一目了然。
JDK14
instanceof模式匹配
该特性可以减少强制类型转换的操作,简化了代码,代码示例:
public class TestInstanceof{
public static void main(String[] args){
//jdk14之前的写法
Object obj = new Integer(1);
if(obj instanceof Integer){
Integer i = (Integer)obj;
int result = i + 10;
System.out.println(i);
}
//jdk14新特性 不用再强制转换了
//这里相当于是将obj强制为Integer之后赋值给i了
if(obj instanceof Integer i){
int result = i + 10;
System.out.println(i);
}else{
//作用域问题,这里是无法访问i的
}
}
}
这个是预览版的功能所以需要使用下面命令编译和运行
编译:
javac --enable-preview -source 14 TestInstanceof.java
运行:
java --enable-preview TestInstanceof
友好的空指针(NullPointerException)提示
jdk14中添加了对于空指针异常友好的提示,便于开发者快速定位空指针的对象。示例代码:
class Machine{
public void start(){
System.out.println("启动");
}
}
class Engine{
public Machine machine;
}
class Car{
public Engine engine;
}
public class TestNull{
public static void main(String[] args){
//这里会报出空指针,但是哪个对象是null呢?
new Car().engine.machine.start();
}
}
我们在运行上面代码的时候,错误信息就可以明确的指出那个对象为null了。此外,还可以使用下面参数来查看:
java -XX:+ShowCodeDetailsInExceptionMessages TestNull
这样编译器会明确的告诉开发者哪个对象是null。
record类型
之前在编写javabean类的时候,需要编写成员变量,get方法,构造方法,toString方法,hashcode方法,equals方法。这些方法通常会通过开发工具来生成,在jdk14中新增了record类型,通过该类型可以省去这些代码的编写。
jdk14编写User
public record User(String name,Integer age){}
通过反编译命令可以看到该字节码文件中的内容,User类是继承了Record类型:
javap -p -private user
编写测试类:
public class TestUser{
public static void main(String[] args){
User u = new User("ahzoo",18);
System.out.println(u);
System.out.println(u.name());
}
}
这个是预览版的功能所以需要使用下面命令编译和运行
编译:
javac --enable-preview -source 14 TestUser.java
运行:
java --enable-preview TestUser
记录类型有自动生成的成员,包括:
-
状态描述中的每个组件都有对应的private final字段。
-
状态描述中的每个组件都有对应的public访问方法。方法的名称与组件名称相同。
-
一个包含全部组件的公开构造器,用来初始化对应组件。
-
实现了equals()和hashCode()方法。equals()要求全部组件都必须相等。
-
实现了toString(),输出全部组件的信息。
JDK15
Sealed Classes
密封类和接口,作用是限制一个类可以由哪些子类继承或者实现。
-
如果指定模块的话,sealed class和其子类必须在同一个模块下。如果没有指定模块,则需要在同一个包下。
-
sealed class指定的子类必须直接继承该sealed class。
-
sealed class的子类要用final修饰。
-
sealed class的子类如果不想用final修饰的话,可以将子类声明为sealed class。
Animal类,在指定允许继承的子类时可以使用全限定名
public sealed class Animal
permits Cat, Dog{//多个子类之间用,隔开
public void eat(){}
}
Cat类
public final class Cat extends Animal{
public void eat(){
System.out.println("123");
}
}
Dog类
public sealed class Dog extends Animal permits Husky {}
Husky类
public final class Husky extends Dog{
}
Test类
public class Test{
public static void main(String[] args){
Cat c = new Cat();
c.eat();
Dog d = new Dog();
}
}
CharSequence新增的方法
该接口中新增了default方法isEmpty(),作用是判断CharSequence是否为空。
TreeMap新增方法
putIfAbsent
、 computeIfAbsent
、computeIfPresent
、compute
、merge
文本块
文本块由预览版变为正式版
JDK16
包装类构造方法的警告
使用包装类的构造方法在编译的时候会出现警告,不建议再使用包装类的构造方法。下面代码在javac编译之后会出现警告。
Integer i = new Integer(8);
不建议使用包装类作为锁对象,倘若使用包装类作为锁对象,在编译时会出现警告。
Integer i = 8;
synchronized(i){
}
新增日时段
在DateTimeFormatter.ofPattern传入B可以获取现在时间对应的日时段,上午,下午等
System.out.println(DateTimeFormatter.ofPattern("B").format(LocalDateTime.now()));
InvocationHandler新增方法
在该接口中添加了下面方法
public static Object invokeDefault(Object proxy, Method method, Object... args)
该方法可以调用父接口中defalut方法,比如有下面接口
interface Girl{
default void eat(){
System.out.println("cucumber");
}
}
实现类
public class Lucy implements Girl{
public void eat(){
System.out.println("banana");
}
}
测试类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test{
public static void main(String[] args) {
Girl girl = new Lucy();
//不使用invokeDefault会调用重写的eat方法
Girl proxy1 = (Girl)Proxy.newProxyInstance(girl.getClass().getClassLoader(),girl.getClass().getInterfaces(),
(obj,method,params)->{
Object invoke = method.invoke(girl);
return invoke;
});
proxy1.eat();
//使用invokeDefault会调用父接口中的default方法
Girl proxy2 = (Girl)Proxy.newProxyInstance(Girl.class.getClassLoader(),new Class<?>[]{Girl.class},
(obj,method,params)->{
if (method.isDefault()) {
return InvocationHandler.invokeDefault(obj, method, params);
}
return null;
});
proxy2.eat();
}
}
JDK17
java17是一个LTS(long term support)长期支持的版本。
switch语法的变化(预览)
Sealed Classes
在jdk15中已经添加了Sealed Classes,只不过当时是作为预览版,经历了2个版本之后,在jdk17中Sealed Classes已经成为正式版了。Sealed Classes的作用是可以限制一个类或者接口可以由哪些子类继承或者实现。
参考文章:https://zhuanlan.zhihu.com/p/390679021
这里还没有评论哦
快来发一条评论抢占前排吧