一、JDK9新特性
1.模块化系统
在我们之前的开发中,当我们导入一个jar包作为依赖时(包括JDK官方库),实际上很多功能我们并不会用到,但是由于它们是属于同一个依赖捆绑在一起,这样就会导致我们可能只用到一部分内容,但是需要引用一个完整的类库,实际上我们可以把用不到的类库排除掉,大大降低依赖库的规模。
于是,Java 9引入了模块机制来对这种情况进行优化,在之前的我们的项目是这样的:
而在引入模块机制之后:
可以看到,模块可以由一个或者多个在一起的 Java 包组成,通过将这些包分出不同的模块,我们就可以按照模块的方式进行管理了。本质上讲也就是说,用模块来管理各个package,通过在module-info.java文件中使用exports声明某个package暴露,不声明默认就是隐藏,在其他模块中的module-info.java文件中使用requires就可以使用其他模块中暴露出的包。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。
模块化的优势
1.模块化的主要目的在于减少内存的开销
2.只须必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
3.改进 Java SE 平台,使其可以适应不同大小的计算设备
4.改进其安全性,可维护性,提高性能
2.JShell交互式编程
类似Python,以交互式的方式对语句和表达式进行求值 ,即写即得 。在jdk的bin包中有jshell命令工具,开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法才可以实现。
3.接口私有方法
在Java 9中,接口更加的灵活和强大,方法可以声明为private,此时方法将不会成为你对外暴露的API的一部分。 注意私有方法必须要提供方法体,并且此方法只能被接口中的其他私有方法或是默认实现调用。
//接口默认都是共有静态常量
public static final int NUM = 10;
//接口默认方法都是抽象方法
public abstract void method1();
//jdk8接口可以有静态方法
public static void method2(){
System.out.println("接口中的静态方法");
}
//jdk8接口可以有默认方法
public default void method3(){
System.out.println("接口中的默认方法");
}
//jdk9接口可以有私有方法
private void method4(){
System.out.println("接口中的私有方法");
}
4.try 语句
Java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过
Java 9 中,用资源语句编写try将更容易,不需要再完整的声明一个变量了,我们可以在try子句中使用已经初始化过的资源,此时的资源是final的
5.String 存储结构变更
String可以不用 char[] 来存储了,改成了 byte[] 加上编码标记,节约了空间。
6.集合类新增of方法
jdk9之前要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。使用of方法可以快速创建。
7.InputStream增强
新增了transferTo方法,可以用来将数据直接传输到 OutputStream
8.Stream API的增强
(1) takeWhile()方法
用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的Stream 中,takeWhile 返回从开头开始的尽可能多的元素。
public static void main(String[] args) throws Exception {
List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
list.stream().takeWhile(t->t<40).forEach(System.out::println);
List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
list2.stream().takeWhile(t->t<7).forEach(System.out::println);
}
(2)dropWhile()方法
dropWhile 的行为与 takeWhile 相反,返回剩余的元素。
public static void main(String[] args) throws Exception {
List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
list.stream().dropWhile(t->t<40).forEach(System.out::println);
List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
list2.stream().dropWhile(t->t<7).forEach(System.out::println);
}
(3)ofNullable()方法
Java 8 中 Stream 不能完全为null,否则会报空指针异常。而 Java 9 中的 ofNullable 方法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空Stream。
public static void main(String[] args) throws Exception {
//允许通过
Stream<String> streams = Stream.of("AA","BB",null);
System.out.println(streams.count());
//不允许通过
/*Stream<Object> stream2 = Stream.of(null);
System.out.println(stream2.count());*/
//允许通过
Stream<Object> stream2 = Stream.ofNullable(null);
System.out.println(stream2.count());
}
(4)iterate() 的重载方法
这个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
public static void main(String[] args) throws Exception {
//原始方式
Stream.iterate(1,i->i+1).limit(50).forEach(System.out::println);
//增强方式
Stream.iterate(1,i->i<60,i->i+1).forEach(System.out::println);
}
9.Optional 类中stream()使用
新增了stream()方法,将一个 Optional 对象转换为一个(可能是空的)Stream 对象。
public static void main(String[] args) throws Exception {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
Optional<List<String>> optional = Optional.ofNullable(list);
optional.stream().flatMap(x->x.stream()).limit(2).forEach(System.out::println);
list.stream().limit(2).forEach(System.out::println);
}
二、JDK10新特性
1.局部变量类型推断
使用var类型名定义的变量可以根据后面的变量值来判断变量的类型。
仅适用于局部变量,且以下情况不适用:
var实际上并不是一个关键字,而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。var并不会改变Java是一门静态类型语言的事实,这种类型推断仅仅发生在编译期间,到最后编译完成后还是会变成具体类型的。
2.集合类新增copyof方法
新增了copyof方法,和of方法一样都是用来创建不可变的集合,不同点是,of方法是直接创建一个不可变集合,copyof方法是根据已有集合复制出一个不可变集合。
使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。
三、JDK11新特性
1.增加ZGC垃圾回收器
GC是java主要优势之一。 然而, 当GC停顿太长, 就会开始影响应用的响应时间。消除或者减少GC停顿时长, java将对更广泛的应用场景是一个更有吸引力的平台。此外, 现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存, 并且无需长时间的GC暂停时间。
ZGC, A Scalable Low-Latency Garbage Collector(Experimental)ZGC, 这应该是JDK11最为瞩目的特性, 没有之一。 但是后面带了Experimental,说明这还不建议用到生产环境。ZGC是一个并发, 基于region, 压缩型的垃圾收集器, 只有root扫描阶段会STW(stop the world), 因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。
优势:
GC暂停时间不会超过10ms
既能处理几百兆的小堆, 也能处理几个T的大堆(OMG)
和G1相比, 应用吞吐能力不会下降超过15%
为未来的GC功能和利用colord指针以及Load barriers优化奠定基础
初始只支持64位系统
2.Optinal增强
新增了isEmpty方法,用于判断value是否为空
3.新增HTTP客户端API
引入了全新的Http Client API,取代之前比较老旧的HttpURLConnection类,新的API主要的特性有:
完整支持HTTP 2.0 或者HTTP 1.1
支持 HTTPS/TLS
有简单的阻塞使用方法
支持异步发送,异步时间通知
支持WebSocket
支持响应式流
public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient(); //直接创建一个新的HttpClient
//现在只需要构造一个Http请求实体,就可以让客户端帮助我们发送出去了(实际上就跟浏览器访问类似)
HttpRequest request = HttpRequest.newBuilder().uri(new URI("https://www.baidu.com")).build();
//现在就可以把请求发送出去了,注意send方法后面还需要一个响应体处理器(内置了很多)这里我们选择ofString直接吧响应实体转换为String字符串
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
//响应实体
System.out.println(response.body());
}
四、JDK14新特性
1.空指针异常的改进
JDK14以前的空指针异常 JDK14之后的空指针异常
五、JDK15新特性
1.新增文本块表达式
使用三引号来表示字符串了,并且可以随意在里面使用特殊字符,包括双引号等,解决了字符串多行换行问题.
public static void main(String[] args) {
var str = """
dsfds
sdfsg " > < !
dsfdsg dfsdf
""";
System.out.println(str);
}
最后编译出来的结果实际上还是会变成一个之前使用了转义字符的字符串
六、JDK16新特性
1.新的switch语法
解决switch语句的一些不规则性,比如case标签之间的默认控制行为,case块中的默认范围,无意义的break语句。从而简化了switch语句的写法。
public static String gradeBefore(int score) {
score /= 10; //既然分数段都是整数,那就直接整除10
String res = null;
switch (score) {
case 10:
case 9:
res = "优秀"; //不同的分数段就可以返回不同的等级了
break; //别忘了break,不然会贯穿到后面
case 8:
case 7:
res = "良好";
break;
case 6:
res = "及格";
break;
default:
res = "不及格";
break;
}
return res;
}
public static String gradeNew(int score) {
score /= 10;
return switch (score) {
case 10, 9 -> "优秀";
case 8, 7 -> "良好";
case 6 -> "及格";
default -> "不及格";
};
}
// yield
public static String gradeNew2(int score) {
score /= 10;
return switch (score) {
case 10, 9 -> "优秀";
case 8, 7 -> "良好";
case 6 -> "及格";
default -> {
System.out.println("做了很多事情");
yield "不及格";
}
};
}