Jdk8ToJdk17

序言

整理下Jdk8到Jdk17中间的所有改动[email protected]

参考资料:

  1. https://blog.csdn.net/guoshengkai373/article/details/122984333

  1. https://www.runoob.com/java/java9-new-features.html

模块化

模块化在jdk9中加入,模块化的好处就是开发者可以根据需要引用某个依赖的指定部分,而不是引入这个依赖的全部。以此达到减少体积以及提高编效率的目的。

如上每个工程只能有1个module-info.java 文件,如上

exports cui.yao.nan.domain;

表示引用了testmoudle1.jar的工程只开发cui.yao.nan.domain包下的类.

如上testmodel2 引用了testmoudle1.jar,

同时必须有module-info.java添加如下内容

requires testmodel1;

否则限制引入的功能不能实现,即取出module-info.java即使testmodel1中有限制,但是在testmodel2中还是能全部引用.

如下在可以用类Student中增加不可引用类的属性也是不可以的.

package-info.java

主要用于给包增加注释.用于生成javadoc时

https://blog.csdn.net/gongm24/article/details/119701533

JShell

REPL(Read Eval Print Loop)意为交互式的编程环境。

JShell 是 Java 9 新增的一个交互式的编程环境工具。它允许你无需使用类或者方法包装来执行 Java 语句。它与 Python 的解释器类似,可以直接 输入表达式并查看其执行结果。

多版本兼容 jar 包

多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本。

通过 --release 参数指定编译版本。

C:\test > javac --release 9 java9/com/runoob/Tester.java

C:\JAVA > javac --release 7 java7/com/runoob/Tester.java

如上分别基于JDK9 和JDK7来创建发布版本(这个特性依然是在JDK9中就被引入了)

同时创建多版本的jar也是可以的

C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9 .

接口方法可私有

在JDK17中,允许interface中携带private方法,这个private方法允许被自身default修饰的方法调用。

package cui.yao.nan.util;

/**
 * @Author: [email protected]
 * @Description: todo
 * @Date: Created at 2023-3-23  10:18
 */
public interface TestInterface {

default String doSomething(){
return getName();
    }

private String getName(){
return "锄禾日当午";
    }
}

String底层变更

在以前的String底层是一个char[], 而现在String底层变更为byte[],以此使得内存的利用率更加高效。

JDK17的String

JDK8的String

增强的StreamAPI

takeWhile

default Stream<T> takeWhile(Predicate<? super T> predicate)

takeWhile() 方法使用一个断言作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false。如果第一个值不满足断言条件,将返回一个空的 Stream。

takeWhile() 方法在有序的 Stream 中,takeWhile 返回从开头开始的尽量多的元素;在无序的 Stream 中,takeWhile 返回从开头开始的符合 Predicate 要求的元素的子集。

import java.util.stream.Stream;
 public class Tester {   
    public static void main(String[] args) {   
       Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())     
    .forEach(System.out::print);         
    } 
}

以上实例 takeWhile 方法在碰到空字符串时停止循环输出,执行输出结果为:abc

dropWhile

default Stream<T> dropWhile(Predicate<? super T> predicate)

dropWhile 方法和 takeWhile 作用相反的,使用一个断言作为参数,直到断言语句第一次返回 false 才返回给定 Stream 的子集。

import java.util.stream.Stream;
 public class Tester {   
    public static void main(String[] args) {      
        Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty()) 
        .forEach(System.out::print);   
    } 
}

以上实例 dropWhile 方法在碰到空字符串时开始循环输出,执行输出结果为:ef

iterate

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

方法允许使用初始种子值创建顺序(可能是无限)流,并迭代应用指定的下一个方法。 当指定的 hasNext 的 predicate 返回 false 时,迭代停止。----类似于for(int i=0;i<10;i+3)

实例

java.util.stream.IntStream;
 public class Tester {   
    public static void main(String[] args) {      
        IntStream.iterate(3, x -> x < 10, x -> x+ 3)
        .forEach(System.out::println);  
     }
 }

执行输出结果为:

  1. 3

  1. 6

  1. 9

ofNullable

static <T> Stream<T> ofNullable(T t)

ofNullable 方法可以预防 NullPointerExceptions 异常, 可以通过检查流来避免 null 值。

如果指定元素为非 null,则获取一个元素并生成单个元素流,元素为 null 则返回一个空流。

其实这个方法允许初始化一个空的流,感觉没有实际用处

import java.util.stream.Stream;
 public class Tester {  
     public static void main(String[] args) {      
        long count = Stream.ofNullable(100).count();      
        System.out.println(count);        
        count = Stream.ofNullable(null).count();      
        System.out.println(count);  
     } 
}

执行输出结果为:

  1. 1

  1. 0

Records

快速构建一个java对象

package cui.yao.nan.controller;

/**
 * @Author: [email protected]
 * @Description: todo
 * @Date: Created at 2023-3-23  9:33
 */
public class TestController {

public static void main(String[] args){
        Student1 s= new Student1("名字",1);
        s.age();
    }

public record Student1(String name,int age){

    }

}

var关键字

现在Java的局部变量可以使用var关键字,可以进行变量类型推断,就像javascript一样。

var a=12;
var b="123";
System.out.println(b.getClass());

新的HttpClient

参考以下类,使用很简单,可以阅读java.net.http中的相关API

java.net.http.HttpClient

java.net.http.HttpRequest

java.net.http.HttpResponse

快速构建集合

List.of("a", "b", "c");
Map.of("key1", "value1", "key2", "value2");

通过Files类快速读写

快速写入

Files.writeString(
    Path.of("./", "tmp.txt"), // 路径
    "hello, jdk11 files api", // 内容
    StandardCharsets.UTF_8); // 编码

快速读取

String s = Files.readString(
    Paths.get("./tmp.txt"), // 路径
StandardCharsets.UTF_8); // 编码

增强的String类

strip等系列方法

相对于trim, strip可以去掉unicode空格, 同时还有stripLeading()和stripTrailing()方法用于分别取出首空和尾空因此不再建议使用trim,而是strip

isBlank方法和isEmpty

前者忽略空格,后者只要有长度就判为非空。通常对于形参校验的情况下,应使用isBlank

lines方法

lines()方法会将一个多行字符串拆分为多个单行字符串,可以方便的以“行“来遍历多行字符串

举例

repeat方法

该方法可以构建一个由多个相同字符串组合的字符串。很绕口,代码解释如下

String str = “hello!”.repeat(2);// 其中,str被赋值为 “hello!hello!”

文本块支持

方便我们调整展示的内容与格式[email protected] 符号是"""三个双引号

增强的instanceof

果然增强了,不就是增加了个强转么~~~~~

Object aObject ="123";

if(aObject instanceof String aa){
    System.out.println(aa.length());
}

增强的switch表达式

由下所示 switch做了如下三件事:

  • 类配判断

  • 类型转换

  • 每个case自动添加break;

另外目前的JDK17的LTS版本并不支持如下的增强,需要预览版本才支持

package cui.yao.nan.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: [email protected]
 * @Description: todo
 * @Date: Created at 2023-3-23  9:33
 */
public class TestController {

public static void main(String[] args){
        Map<String,Object> mapTest=new HashMap<>();

        mapTest.put("string","String");
        mapTest.put("integer",12);

        mapTest.keySet().forEach(e->{
switch(mapTest.get(e)){
case String a->{ System.out.println("i am String");}
case Integer a->{System.out.println("i am Integer");}
default -> throw new IllegalStateException("Unexpected value: " + mapTest.get(e));
            }
        });
    }

}

NumberFormat增加了压缩数字的支持

String number = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT).format(1000);// 其中number = “1k“

码农福音,增强的NullPointerExceptions

增强后的NullPointerExceptions可以将具体引发空指针的变量名称和位置披露出来,对于新手来说,可以更方便问题排查。

密封类

密封 类的目的是为了限制子类的过度使用,父类的开发者必须声明哪些子类可以继承该父类,以确保不会出现未限定的子类继承父类,导致程序出现预料之外的问题--有点类似于集合的下边界的限制

代码:public sealed class Job permits Developer, Manager, Salesman {}

sealed代表是密封类,permits是指允许哪些子类对Job父类的继承

案例演示:

父类

public sealed class Job permits Developer,Manager,Salesman{}

限定了只有Developer,Manager,Salesman这个类可以继承

密封类的子类必须是final类、sealed类或non-sealed类----

final类,不允许被继承

sealed类,蜜蜂类

non-sealed类 可以被任何类继承

Manager.java

public final class Manager extends Job{}

Developer.java

public sealed class Developer extends Job permits UIDeveloper,WebDeveloper{}

子类Developer又声明了蜜蜂类,并只允许UIDeveloper,WebDeveloper继承

UIDeveloper.java

//non-sealed类 可以被任何类继承
public non-sealed class UIDeveloper extends Developer{}

WebDeveloper

//final类,不允许被继承
public final class WebDeveloper extends Developer{}

注意:父类和子类只允许在同一个包下

示例

package cui.yao.nan.controller;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**
 * @Author: [email protected]
 * @Description: todo
 * @Date: Created at 2023-3-23  9:33
 */
public class TestController {

public static void main(String[] args){
    }

public  sealed class Hello permits Hello1{}

public final class Hello1 extends Hello{

    }

}

反射相关

在java.lang.Class中新增了两个方法

boolean isSealed()

Class<?>[] getPermittedSubclasses()

前者用于判断该类是否为密封类,后者则用来获得当前密封类所允许扩展的Class列表。

直接打包成可执行程序

支持将Java程序打包为对应平台的可执行程序

linux: deb和rpm

mac: pkg和dmg

Windows: msi和exe

假如我们在lib目录下有一个jar包组成的应用,并且main.jar包含main方法,则可以使用下面的语句产生对应平台的可执行程序

jpackage --name myapp --input lib --main-jar main.jar

如果main.jar的MANIFEST.MF没有指定main函数,则需要在命令行中指定

jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main

猜你喜欢

转载自blog.csdn.net/cuiyaonan2000/article/details/129724696