发布:admin2025-12-16 03:16:50 5254条浏览分类:跨服战场
一、JDK9新特性
1. 概述
JDK9新特性主要包括:
模块化系统
JShell
只读集合工厂方法
接口的私有方法
String存储结构改变
try...catch升级
平台日志API和服务
垃圾回收器
2. 模块化系统
没有使用模块化时存在的问题:
导入依赖时,需要加载全部的包,影响系统性能。
Java 运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~60MB的内存加载,主要原因是JVM需要加载rt.jar,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)
当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。不同版本的类库交叉依赖导致让人头疼的问题,这些都阻碍了 Java 开发和运行效率的提升。
很难真正地对代码进行封装, 而系统并没有对不同部分(也就是 JAR 文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到,这样就会导致无意中使用了并不想被公开访问的 API。
本质上讲也就是说,用模块来管理各个package,通过声明某个package暴露,模块(module)的概念,其实就是package外再裹一层,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。
使用模块化系统,可以按需导入对应的模块。
实现目标
模块化的主要目的在于减少内存的开销
只须必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
改进 Java SE 平台,使其可以适应不同大小的计算设备
改进其安全性,可维护性,提高性能
使用
在src下创建module-info.java
导出:
module xxx{
exports 包名/模块;
}
导入:
module xxx{
requires 包名/模块;
}
3. JShell命令
像Python 和 Scala 之类的语言早就有交互式编程环境 REPL (read - evaluate - print - loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。
4. 接口的私有方法
public interface JDK9Demo4 {
//接口默认都是共有静态常量
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("接口中的私有方法");
}
}
5. 钻石操作符升级
Comparator
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
在jdk8中 上面的代码会报错:<>必须写明类型,jdk9对<>做了升级,不写也不报错。
6. try...catch
在jdk8中,可以自动关闭资源,但必须在try子句中初始化。
jdk9可以在外部初始化,try子句写对象名,也可以自动关闭。
try(inputStream;outputStream){
}
7. String存储结构变更
不再使用char[]存储,改为byte[],节省空间。
同样的,StringBuffer 和 StringBuilder也做了存储结构的变更。
8. of() 创建只读集合
jdk9引入了of()方法,可以方便的创建只读集合
public class Demo5 {
public static final List
public static void main(String[] args) {
//jdk8以前创建只读集合
List
list.add("张三");
list.add("李四");
list.add("王五");
Collection
// list2.add("赵六");
// System.out.println(list2);
//jdk9创建只读集合
List
System.out.println(list3);
Set
System.out.println(set1);
Map
System.out.println(map);
}
}
9. InputStream增强
使用 transferTo 可以将输入流中的内容直接交给输出流输出
10. stream API增强
在 Java 9 中,Stream API 变得更好,Stream 接口中添加了 4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。现在可以通过 Optional 的新方法 stream() 将一个 Optional 对象转换为一个(可能是空的) Stream 对象。
10.1 takeWhile()
用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的Stream 中,takeWhile 返回从开头开始的尽量多的元素。
public static void main(String[] args) throws Exception {
List
list.stream().takeWhile(t->t<40).forEach(System.out::println);
List
list2.stream().takeWhile(t->t<7).forEach(System.out::println);
}
10.2 dropWhile()
dropWhile 的行为与 takeWhile 相反,返回剩余的元素。
10.3 ofNullable()
Java 8 中 Stream 不能完全为null,否则会报空指针异常。
而 Java 9 中的 ofNullable 方法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空Stream。
public static void main(String[] args) throws Exception {
//允许通过
Stream
System.out.println(streams.count());
//不允许通过
/*Stream
System.out.println(stream2.count());*/
//允许通过
Stream
System.out.println(stream2.count());
}
10.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);
}
10.5 Optional类中stream()使用
public static void main(String[] args) throws Exception {
List
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
Optional> optional = Optional.ofNullable(list);
optional.stream().flatMap(x->x.stream()).limit(2).forEach(System.out::println);
list.stream().limit(2).forEach(System.out::println);
}
Optional接收一个集合对象,底层也是用集合容器进行存储,所以使用一次流进行遍历得到的是集合对象,
调用flatMap方法 能获取到集合中的元素
二、JDK10新特性
1. 局部变量类型推断
使用var声明变量,var进行类型推断
public class Demo1 {
public static void main(String[] args) {
method1();
}
public static void method1(){
var i = 1;
var list = new ArrayList
list.add("张三");
list.add("李四");
System.out.println(list);
}
}
var不是一个关键字。
var没有改变java是强语言的本质,只是进行类型的推断。
以下情况不能推断:
public static void method2(){
//由于值是null,类型无法推断
// var i = null;
//方法引用无法使用var
//var a = System.out::println;
//lamdba无法推断var的类型,故不能用
/* Function
return a+"";
};*/
/* var fun2 = (Integer a)->{
return a+"";
};*/
//静态数组后面不加类型的时候推断不出来var的类型,故不能用
int[] arr = new int[]{1,2,3};
int[] arr2 = {1,2,3};
//var arr3 = {1,3,4};
}
2. 新增只读集合方法 copyOf()
public static void main(String[] args) throws Exception {
//示例1
var list1 = List.of("AA","BB","CC");
var list2 = List.copyOf(list1);
System.out.println(list1==list2);//true
//示例2
var list3 = new ArrayList
list3.add("AA");
list3.add("BB");
List
System.out.println(list3==list4); //false
}
copyOf 方 法 会 先 判 断 来 源 集 合 是 不 是AbstractImmutableList 类型的,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。
示例2因为用的 new 创建的集合,不属于不可变 AbstractImmutableList 类的子类,所以 copyOf 方法又创建了一个新的实例,所以为false。
注意:使用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. Optional加强
3. 新增HTTP客户端API
HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年,HTTP2才成为标准。
HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。 HTTP/2允许服务器“push”数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据。
这是 Java 9 开始引入的一个处理 HTTP 请求的的 HTTP Client API,该API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你可以在java.net 包中找到这个 API。
它 将 替 代 仅 适 用 于 blocking 模 式 的 HttpURLConnection(HttpURLConnection是在HTTP 1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket 和 HTTP/2的支持
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request =
HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
HttpResponse.BodyHandler
HttpResponse
String body = response.body();
System.out.println(body);
}
四、JDK14新特性
在NullPointerException时,指明为null的变量
之前:
jdk14:
五、JDK15新特性
新增 text blocks 文本块,解决多行字符串换行问题
public static void main(String[] args) {
//jdk15增加文本块
String str = """
hello
world
hahaha
""";
}
六、JDK16新特性
在Java16中正式发布Switch升级,其目的是为了解决switch语句的一些不规则性成为障碍
比如case标签之间的默认控制行为
case块中的默认范围
无意义的break语句。
public static void main(String[] args) {
int level = new Random().nextInt(4);
String strLevel;
switch (level){
case 1 -> strLevel="优秀";
case 2 -> strLevel="良好";
default -> strLevel="一般";
}
System.out.println(strLevel);
}
还可以写成:
public static void main(String[] args) {
int level = new Random().nextInt(4);
String strLevel = switch (level){
case 1-> "优秀";
case 2-> "良好";
default -> "一般";
};
System.out.println(strLevel);
}
根据月份判断季节:
public static void main(String[] args) {
int level = new Random().nextInt(12);
String jiJi = null;
switch (level){
case 3,4,5 -> jiJi = "春天";
case 6,7,8 -> jiJi = "夏天";
case 9,10,11 -> jiJi = "秋天";
case 12,1,2 -> jiJi = "冬天";
};
System.out.println(jiJi);
}
还有:
public static void main(String[] args) {
int level = new Random().nextInt(4);
String strLeave = switch (level){
case 1 -> {
System.out.println("优秀");
yield "优秀";
}
default -> "进步空间很大";
};
System.out.println(strLeave);
}
虽然写法更简单了,但是编译后的代码还是原本的格式,只是做了翻译。