18.1 JDK9
1、JDK目录结构的改变
2、模块化系统
Java和相关生态在不断丰富的同时也越来越暴露出一些问题:
- Java运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~60MB的内存架子啊,主要原因是JVM需要加载rt.jar,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)。
- 每一个公共类都可以被类路径下任何其他的公共类所访问到,这样就会导致无意中使用了并不像被公开访问的API。
- 实例:
// 1、module2的module-info.java中,导出本模块需要暴露的包
module module2 {
exports com.xianhuii;
}
// 2、module1的module-info.java中,导入需要的模块
module module1 {
requires module2;
}
// 3、module1中的类中即可访问到module2中的类
import com.xianhuii.Person;
public class ModuleTest {
public static void main(String[] args) {
Person person = new Person();
}
}3、Java的REPL工具:jshell
jshell> /help
| 键入 Java 语言表达式, 语句或声明。
| 或者键入以下命令之一:
| /list [<名称或 id>|-all|-start]
| 列出您键入的源
| /edit <名称或 id>
| 编辑源条目
| /drop <名称或 id>
| 删除源条目
| /save [-all|-history|-start] <文件>
| 将片段源保存到文件
| /open <file>
| 打开文件作为源输入
| /vars [<名称或 id>|-all|-start]
| 列出已声明变量及其值
| /methods [<名称或 id>|-all|-start]
| 列出已声明方法及其签名
| /types [<名称或 id>|-all|-start]
| 列出类型声明
| /imports
| 列出导入的项
| /exit [<integer-expression-snippet>]
| 退出 jshell 工具
| /env [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>] ...
| 查看或更改评估上下文
| /reset [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>]...
| 重置 jshell 工具
| /reload [-restore] [-quiet] [-class-path <路径>] [-module-path <路径>]...
| 重置和重放相关历史记录 -- 当前历史记录或上一个历史记录 (-restore)
| /history [-all]
| 您键入的内容的历史记录
| /help [<command>|<subject>]
| 获取有关使用 jshell 工具的信息
| /set editor|start|feedback|mode|prompt|truncation|format ...
| 设置配置信息
| /? [<command>|<subject>]
| 获取有关使用 jshell 工具的信息
| /!
| 重新运行上一个片段 -- 请参阅 /help rerun
| /<id>
| 按 ID 或 ID 范围重新运行片段 -- 参见 /help rerun
| /-<n>
| 重新运行以前的第 n 个片段 -- 请参阅 /help rerun
|
| 有关详细信息, 请键入 '/help', 后跟
| 命令或主题的名称。
| 例如 '/help /list' 或 '/help intro'。主题:
|
| intro
| jshell 工具的简介
| keys
| 类似 readline 的输入编辑的说明
| id
| 片段 ID 以及如何使用它们的说明
| shortcuts
| 片段和命令输入提示, 信息访问以及
| 自动代码生成的按键说明
| context
| /env /reload 和 /reset 的评估上下文选项的说明
| rerun
| 重新评估以前输入片段的方法的说明4、接口的私有方法
在Java9中,可以定义私有方法,提供给默认方法使用。
public interface MyInterface {
void methodAbstract(); // 访问权限是public
static void methodStativc() { // 访问权限是public
System.out.println("静态方法");
}
default void methodDefault() { // 访问权限是public
System.out.println("默认方法");
methodPrivate(); // 调用私有方法
}
private void methodPrivate() {
System.out.println("私有方法");
}
}
public class MyInterfaceImpl implements MyInterface {
@Override
public void methodAbstract() {
}
// @Override
// public void methodDefault() {
//
// }
public static void main(String[] args) {
// 接口中的静态方法只能由自己调用,接口的实现类不能调用
MyInterface.methodStativc();;
MyInterfaceImpl impl = new MyInterfaceImpl();
// 实现类实例调用接口中的默认方法,如果没有重写,则可间接调用接口中的私有方法
impl.methodDefault();
// 实现类实例不能调用接口中的私有方法
}
}5、钻石操作符的语法升级
import org.junit.jupiter.api.Test;
import java.util.Comparator;
public class DiamondTest {
@Test
public void test() {
// 砖石操作符与匿名内部类在Java8中不能共存(new Comparator<Object>()),在Java9可以。
Comparator<Object> com = new Comparator<>() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
}
}6、try结构的语法升级
Java8中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStreamReader;
public class JDKTest {
/**
* Java 8之前
*/
@Test
public void test1() {
InputStreamReader reader = null;
try {
reader = new InputStreamReader(System.in);
char[] cbuf = new char[20];
int len;
while ((len = reader.read(cbuf)) != -1) {
String str = new String(cbuf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Java 8
*/
@Test
public void test2() {
try (InputStreamReader reader = new InputStreamReader(System.in)) {
char[] cbuf = new char[20];
int len;
while ((len = reader.read(cbuf)) != -1) {
String str = new String(cbuf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Java 9
* 此时的资源(reader)是默认是常量(final)。
*/
@Test
public void test3() {
InputStreamReader reader = new InputStreamReader(System.in);
try (reader) {
char[] cbuf = new char[20];
int len;
while ((len = reader.read(cbuf)) != -1) {
String str = new String(cbuf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}7、String存储结构变更
- 改变:char[] —> byte[]
- String、StringBuffer、StringBuilder都变了。
- 原因:节省空间。
- Most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.
- Change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field.
8、集合工厂方法创建只读集合
- List、Set、Map的of()静态方法。
import org.junit.jupiter.api.Test;
import java.util.*;
public class JDKTest {
/**
* Java8
*/
@Test
public void test1() {
List<String> nameList = new ArrayList<>();
nameList.add("aa");
nameList.add("bb");
nameList.add("cc");
// 返回的是一个只读的集合
nameList = Collections.unmodifiableList(nameList);
// 返回的是一个只读的集合
List<Integer> list = Arrays.asList(1, 2, 3);
}
/**
* Java9
*/
@Test
public void test2() {
List<Integer> list = List.of(1, 2, 3, 4, 5);
Set<Integer> integers = Set.of(1, 2, 3, 4, 5);
Map<String, Integer> a = Map.of("a", 1, "b", 2);
Map<String, Integer> kvMap = Map.ofEntries(Map.entry("a", 1), Map.entry("b", 2));
}
}9、InputStream加强
InputStream的新方法:transferTo()。
直接把输入流中的所有数据直接自动地赋值到输出流中。
import org.junit.jupiter.api.Test;
import java.io.*;
public class JDKTest {
@Test
public void test1() {
ClassLoader classLoader = this.getClass().getClassLoader();
try (InputStream is = classLoader.getResourceAsStream("hello.txt");
OutputStream os = new FileOutputStream("hello1.txt")) {
is.transferTo(os); // 把输入流中的所有数据直接自动地赋值到输出流中
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}10、增强的Stream API
Stream接口中添加了4个新的方法:takeWhile、dropWhile、ofNullable、以及iterate的重载方法。
takeWhile():返回从开头开始的按照指定规则尽量多的元素
dropWhile():与takeWhile相反,返回剩余的元素。
ofNullable():可以创建单个null值。
iterate():自定义终止条件。
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class JDKTest {
@Test
public void test1() {
List<Integer> list = Arrays.asList(23, 41, 534, 543, 23, 12, 43);
list.stream().takeWhile(i -> i < 100).forEach(System.out::println); // 23, 41
System.out.println("+++++++++++++++++++");
list.stream().dropWhile(i -> i < 100).forEach(System.out::println); // 534, 543, 23, 12, 43
System.out.println("+++++++++++++++++++");
// of()参数中的多个元素,可以包含null值,
Stream<Integer> integerStream = Stream.of(1, 2, 3, null);
integerStream.forEach(System.out::println);
// Stream<Object> objectStream = Stream.of(null); // of()参数不能存储单个null,×
// objectStream.forEach(System.out::println); // 此处会报异常
Stream<Object> objectStream2 = Stream.of(null, null); // of()参数可以包含多个null,√
Stream<Object> objectStream1 = Stream.ofNullable(null); // ofNullable()可以创建单个null值,√
System.out.println(objectStream1.count()); // 0
System.out.println("+++++++++++++++++++");
Stream.iterate(0, x -> x < 100, x -> x+1).forEach(System.out::print);
}
}11、Optional的新方法:stream()
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class JDKTest {
@Test
public void test1() {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
Optional<List<String>> optional = Optional.ofNullable(list);
Stream<List<String>> stream = optional.stream();
stream.flatMap(x -> x.stream()).forEach(System.out::println);
}
}12、JavaScript引擎升级:Nashorn
- JDK 9包含一个用来解析Nashorn的ECMAScript的语法树的API。这个API使得IDE和服务端框架不需要依赖Nashorn项目的内部实现类,就能分析ECMAScript代码。
18.2 JDK10
1、Local-Variable Type Inference(局部变量类型推断)
- 局部变量的显示类型声明,常常被认为是不必须的,给一个好听的名字经常可以清楚地表达出下面应该怎样继续。
- 减少了啰嗦和形式的代码,避免了信息冗余,而且对其了变量名,更容易阅读。
- 工作原理:在处理var时,编译器先是查看表达式右边部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中。
- 注意:
- var不是一个关键字:除了不能用它作为类名,其他都可以。
- 这不是JavaScript:var并不会改变Java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。
2、集合中新增copyOf(),用于创建一个只读的集合
- copyOf(Xxx coll):
- 如果参数coll本身就是一个只读集合,则copyOf()返回值即为coll。
- 如果参数coll不是一个只读集合,则copyOf()返回一个新的集合,这个集合是可读的。
18.3 JDK11
- JDK11是一个长期支持版本(LTS,Long-Term-Support)。
1、String新增的方法
import org.junit.jupiter.api.Test;
public class JDKTest {
@Test
public void test1() {
// isBlank():判断字符串是否为空白
System.out.println(" ".isBlank()); // true
System.out.println("\t \n ".isBlank()); // true
// strip():去除首尾空白
System.out.println("\t abc \n ".strip()); // "abc"
System.out.println("\t abc \n ".trim()); // "abc"
// stripTrailing():去除尾部空格
System.out.println("\t abc \t \n ".stripTrailing()); // " abc"
// stripLeading():去除首部空格
System.out.println("\t abc \t \n ".stripLeading()); // "abc "
// repeat(int count):复制count次
String str1 = "abc";
String str2 = str1.repeat(5);
System.out.println(str2); // "abcabcabcabcabc"
// lines().count():行数统计
String str3 = "\n\n\n";
System.out.println(str3.lines().count()); // 3
}
}2、Optional加强
import org.junit.jupiter.api.Test;
import java.util.Optional;
public class JDKTest {
@Test
public void test1() {
Optional<Object> op = Optional.empty();
System.out.println(op.isPresent()); // 判断内部的value是否存在
System.out.println(op.isEmpty()); // 判断内部的value是否为空
op = Optional.of("abc");
var obj = op.orElseThrow(); // value非空,返回value;否则抛异常:NoSuchElementException
System.out.println(obj);
Optional<String> op1 = Optional.of("hello");
// or:value非空,返回对应的Optional;value为空,返回形参封装的Optional
Optional<Object> op2 = op.or(() -> op1);
System.out.println(op2);
}
}3、全新的HTTP客户端API
- HttpClient替换原有的HttpURLConnection。
4、更简化的编译运行程序
// 之前
javac Test.java
java Test
// JDK11
java Test.java要求:
- 执行源文件中的第一个类,第一个类中必须要有main方法。
- 第一个类可以不是public的(类名与源文件名不同)。
- 在源文件中的,不可以引用其他源文件的类。即当前源文件中的类只能使用本文件中的类。
5、废弃Nashorn引擎。
6、ZGC
- ZGC,A Scalable Low-Latency Garbage Collector(Experimental)。

京公网安备 11010502036488号