JDK9-17
create by nohi 20230117
简要记录JDK变化
JDK9
1 模块化
目标
(1)可靠的配置
(2)强封装
(3)模块化JDK/JRE
内容
requires其他模块(或依赖于)的列表
requires语句用于指定一个模块对另一个模块的依赖,requires语法如下: requires [transitive] [static] <module>; <module>:是当前模块读取的另一个模块的名称; static:则<module>模块在编译时是必需的,但在运行时是可选的; transitive:级联依赖;
exports包列表(其public API),其他模块可以使用
open的包(整个API,共有和私有),其他模块可以反射调用
使用的服务列表
提供的服务的实现列表
聚合模块
可以创建一个不包含任何代码的模块,它收集并重新导出其他模块的内容,这样的模块称为聚合模块。假设有一个模块依赖于五个模块,可以为这五个模块创建一个聚合模块,现在你的模块只要依赖于一个模块--聚合模块。
声明模块
[open] module <moduleName> { <module-statement>; ...... }
open修饰符是可选的,它声明一个开放的模块,一个开放的模块导出所有的包,以便其他模块使用反射访问。
<moduleName>
是要定义的模块的名称,<module-statement>
是一个模块语句。模块声明中可以包含零个或多个模块语句:导出语句(exports),导出模块,其他模块访问。
exports <package> to <module1>, <module2>;
开放语句(opens),开放当前模块,其他模块可以访问,包括反射调用等。
opens <package>; opens <package> to <module1>, <module2>…… <package>仅用于深层反射到<module1>,<module2>等。
需要语句(requires),声明模块对另一个模块的依赖关系。
requires <module>; requires transitive <module>; requires static <module>; requires transitive static <module>; static标示在编译时的依赖是强制的,但在运行时是可选的:requires static N意味着模块M需要模块N,模块N必须在编译时出现才能编译模块M,而在运行时存在模块N是可选的。 transitive当前模块依赖其他模块具有隐式依赖性,假设有三个模块P,Q和R,假设模块Q包含requires transitive R语句,如果模块P包含requires Q,这意味着模块P隐含依赖模块R。
使用语句(uses),表达服务消费。
use语句可以指定服务接口的名字,当前模块就会发现它,使用java.util.ServiceLoader类进行加载:
uses
<service-interface>
提供语句(provides),表达服务提供。
模拟约束
(1)将包拆分成多个模块是不允许的,也就是说,同一个包不能在多个模块中定义;
(2)不能同时访问多个模块中的相同软件包;
(3)模块图不能包含循环依赖,也就是说两个模块不能彼此读取,如果需要,他们应该是一个模块,而不是两个;
(4)模块声明不支持模块版本,需要使用jar工具或其他一些工具(javac)将模块的版本添加为类文件属性;
(4)模块系统没有子模块的概念,com.jdk9.address和com.jdk9.address.child是两个单独的模块。
目测模块化,exports目录不能包含下级目录。
module jdk9.module1 {
exports nohi.jdk9.module1.user;
exports nohi.jdk9.module1.user.addres;
}
2 jshell
命令行窗口,快速的运行一些简单的代码
╰─➤ jshell # 调用jshell命令窗口
| 欢迎使用 JShell -- 版本 18.0.2
| 要大致了解该版本, 请键入: /help intro
jshell> System.out.println("HelloWorld");
HelloWorld
jshell> /exit # 退出
| 再见
3 接口私有方法
public interface MyInterface {
//定义私有方法
private void m1() {
System.out.println("123");
}
//default中调用
default void m2() {
m1();
}
}
4 改进的try with resource
public class TryWithResouce {
public void testTryWithResource(String src, String target) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(target);
try (fis; fos) {
byte[] is = new byte[1024];
int length;
while ((length = fis.read(is)) > -1) {
fos.write(is, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 测试类
@org.junit.jupiter.api.Test
void testTryWithResource() throws FileNotFoundException {
TryWithResouce tr = new TryWithResouce();
String src = "./pom.xml";
String target = "./pom_target.xml";
tr.testTryWithResource(src, target);
}
5 不能使用下划线命名变量
6 String字符串的变化,String内部的char数组改成了byte数组
JDK10
1.局部变量类型推断
var str = "ABC"; //根据推断为 字符串类型
var l = 10L;//根据10L 推断long 类型
var flag = true;//根据 true推断 boolean 类型
var flag1 = 1;//这里会推断boolean类型。0表示false 非0表示true
var list = new ArrayList<String>(); // 推断 ArrayList<String>
var stream = list.stream(); // 推断 Stream<String>
其他
- 将JDK多存储库合并为单存储库
- 垃圾回收接口
- 并行Full GC 的G1
- 应用数据共享
- 线程局部管控
- 移除Native-Header Generation Tool (javah)
- Unicode 标签扩展
- 备用内存设备上分配堆内存
- 基于实验JAVA 的JIT 编译器
- Root 证书
- 基于时间的版本控制
JDK11
2018年9 月 26 日
ZGC、Http Client
参考:https://www.jianshu.com/p/84a6050c5391
1 直接运行
java Hello.java
2 String新增方法
// unicode 空白符
char c = '\u2000';
String str = c + "abc" + c;
System.out.println(String.format("[%s]", str));
System.out.println(String.format("trim[%s]", str.trim()));
System.out.println(String.format("strip[%s]", str.strip()));
str = " abc ";
System.out.println(String.format("[%s]", str));
System.out.println(String.format("trim[%s]", str.trim()));
System.out.println(String.format("strip[%s]", str.strip()));
输出
[ abc ] trim[ abc ] strip[abc] [ abc ] trim[abc] str.trim()可以删除空格 strip[abc]
// 判断字符串是否为空白
" ".isBlank(); // true
// 去除首尾空格
" Javastack ".strip(); // "Javastack"
// 去除尾部空格
" Javastack ".stripTrailing(); // " Javastack"
// 去除首部空格
" Javastack ".stripLeading(); // "Javastack "
// 复制字符串
"Java".repeat(3);// "JavaJavaJava"
// 行数统计
"A\nB\nC".lines().count(); // 3
3 局部变量类型推断
Lambda表达式中,可以使用var关键字来标识变量,变量类型由编译器自行推断
public static void main(String[] args) {
Arrays.asList("Java", "Python", "Ruby")
.forEach((var s) -> {
System.out.println("Hello, " + s);
});
}
4 Stream
// 0
Stream.ofNullable(null).count();
// [1, 2]
Stream.of(1, 2, 3, 2, 1).takeWhile(n -> n < 3).collect(Collectors.toList());
// [3, 2, 1]
Stream.of(1, 2, 3, 2, 1).dropWhile(n -> n < 3).collect(Collectors.toList());
5 Optional
// javastack
var msg = Optional.of("javastack").orElseThrow();
System.out.println("msg:" + msg);
System.out.println("msg.orElse:" + Optional.ofNullable(null).orElse("11111"));
// 1
long count = Optional.of("javastack").stream().count();
System.out.println("count:" + count);
// javastack
var obj = Optional.ofNullable(null).or(() -> Optional.of("javastack")).get();
System.out.println("obj:" + obj);
// 没有值,抛出异常
System.out.println("msg.orElse:" + Optional.ofNullable(null).orElseThrow());
6 InputStream
transferTo inputStrem -> OutputStream
var classLoader = ClassLoader.getSystemClassLoader();
var inputStream = classLoader.getResourceAsStream("application.yml");
var javastack = File.createTempFile("application-target", "txt");
try (var outputStream = new FileOutputStream(javastack)) {
inputStream.transferTo(outputStream);
}
System.out.println("java.io.tmpdir:" + System.getProperty("java.io.tmpdir"));
7 HTTP Client API
var request = HttpRequest.newBuilder().uri(URI.create("https://www.baidu.com")).GET().build();
var client = HttpClient.newHttpClient();
// 同步
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
// 异步
client.sendAsync(request,HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body).thenAccept(System.out::println);
8 读写文件
对Files类增加了writeString和readString两个静态方法,可以直接把String写入文件,或者把整个文件读出为一个String:
System.out.println(Path.of("./").toAbsolutePath());;
Files.writeString(
// 路径
Path.of("./", "tmp.txt"),
// 内容
"hello, jdk11 files api",
// 编码
StandardCharsets.UTF_8);
String s = Files.readString(
// 路径
Paths.get("./tmp.txt"),
// 编码
StandardCharsets.UTF_8);
System.out.println(s);
JDK12
1 switch
无break
static final int MONDAY = 1;
static final int TUESDAY = 2;
static final int WEDNESDAY = 3;
static final int THURSDAY = 4;
static final int FRIDAY = 5;
static final int SATURDAY = 6;
static final int SUNDAY = 7;
public void doSwitch(int day) {
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
default -> System.out.println("default");
}
}
2 Shenandoah GC
Redhat 主导开发的 Pauseless GC 实现,从大概 2013 年开始研发,终于取得了重要的阶段性成果,与其他 Pauseless GC 类似,Shenandoah GC 主要目标是 99.9% 的暂停小于 10ms,暂停与堆大小无关等。
3 支持Unicode 11.0
JDK 12版本包含对Unicode 11.0.0的支持。 在支持Unicode 10.0.0的JDK 11发行之后,Unicode 11.0.0引入了JDK 12现在包含的以下新功能:
- 684个新字符
- 11个新blocks
- 7个新脚本。
4 NumberFormat增加了对以紧凑格式格式化数字的支持
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000);
System.out.println("result1:" + result);
result = fmt.format(1000000);
System.out.println("result2:" + result);
# 结果
result1:1K
result2:1M
JDK13
1 switch表达式
传统的case ...:labels(需要break)或新case ...->labels(不需要break) ,还有另一个新语句,用于从switch表达式产生值
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
2 文本块
String text = """
第一行
第二行
第三行
""";
System.out.println(text);
java.lang.Character支持12.1级别的Unicode字符数据库,其中12.0自11.0起增加了554个字符,总共137,928个字符。
3 ZGC的增强
4 支持Unicode 12.1
JDK14
1 instanceof匹配
Object obj = 1;
// 自动传值至变量abc
if (obj instanceof Integer abc) {
System.out.println(abc);
}
2 空指针提示
3 record类型
record Student(String name, int age) {
public void daydayUp() {
System.out.println(String.format("[%s][%s] daydayup", name, age));
}
}
@Test
public void testRecord() {
Student student = new Student("NOHI", 18);
System.out.println(student);
student.daydayUp();
}
JDK15
2020/09/15 发布
1 密封类Sealed Classes (预览特性)
2 文本块功能转正
3 Shenandoah 垃圾回收算法转正
JDK 16
2021/03/16发布
1 instanceof 功能转正
if (object instanceof Kid kid) {
// ...
} else if (object instanceof Kiddle kiddle) {
// ...
}
2 Records 转正
3 ZGC
ZGC 最早是在 JDK 11 中集成进来的,在 JDK 15 中正式转正。
这个版本则是为了让 ZGC 支持并发栈处理,解决了最后一个重大瓶颈,把 ZGC 中的线程栈处理从安全点移到了并发阶段。并且还提供了一种机制,使得其他 HotSpot 子系统可以通过该机制延迟处理线程栈。
JDK17
1 switch
public void animalMoving(Animal animal) {
switch (animal){
case Rabbit r -> r.run();
case Bird b -> b.fly();
case null -> System.out.println("null....");
default -> animal.moving();
}
}
2 密封类转正
JDK18
1 默认使用UTF-8字符编码
-Dfile.encode=UTF-8
2 简单web服务器
jwebserver
3 将被移除的方法
Object中的finalize方法,Thread中的stop方法将在未来被删除