序言
整理下Jdk8到Jdk17中间的所有改动[email protected]
参考资料:
模块化
模块化在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);
}
}
执行输出结果为:
3
6
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
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