# java9特性

## 语法变更

### 钻石操作符

在Java8中，匿名内部类不支持使用钻石操作符：

```java
Comparator<String> comparator = new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return 0;
    }
};
```

在Java9中，已经支持匿名内部类泛型推断：

```java
Comparator<String> comparator = new Comparator<>() {
    @Override
    public int compare(String s1, String s2) {
        return 0;
    }
};
```

### try 语句升级

```java
InputStreamReader isr = new InputStreamReader(new FileInputStream("d:/aaa.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/aaa.txt"));
try (isr; osw) {
    isr.read();
} catch(Exception e) {
    e.printStrackTrace();
}
```

### 下划线标识符限制

Java8可以单独使用下划线定义变量，而Java9中则不允许了。

```java
String _  = ""; // Java8 编译通过，Java9报错
```

## API变更

### 接口中的私有方法

Java9中可以在Interface中定义private方法:

```java
public interface MyInterface {

    private int add(){
        // xxx
    }

}
```

### String底层存储结构

String的存储结构由 `char[]` 变为了 `byte[]`

### Stream API新增方法

Stream新增四个API方法：

```java
// takeWhile，从头遍历并取出符合条件的集合元素，当遇到不符合的元素就停止处理
// 从头遍历整型集合中的偶数，当遇到一个奇数时，就退出
list.stream().takeWhile(e -> e % 2 == 0).forEach(System.out::println);

// dropWhile，从头遍历并删除符合条件的集合元素，当遇到不符合的元素就停止处理
// 从头遍历整型集合中的偶数并删除这个偶数，当遇到一个奇数时，就退出
list.stream().dropWhile(e -> e % 2 == 0).forEach(System.out::println);

// ofNullable，允许创建Stream时，创建一个仅有一个null值作为元素的Stream
Stream.of(null); // 报错
Stream.ofNullable(null) // 不报错

// iterate，给定一个种子，指定条件和迭代方式来获取流
// 1.8中已经存在generate和iterate方法
// 随机10个数，然后打印
Stream.generate(Math::radom).limit(10).forEach(System::out::println);
// 生成10个数，从0开始，每个数间隔增加2
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
// java9提供了对iterate的重载，功能与上一行代码类似
Stream.iterate(0, t -> t < 10, t -> t + 1).forEach(System.out::println);
```

此外，Stream的一些方法实现了与Optional的结合：

```java
Optional<Integer> maxOptional = list.stream().max();

// Optional也可以获取到他的Stream
maxOptional.stream();
```

### InputStream新增API

InputStream新增`transferTo`方法，此方法会创建缓冲区使用while循环将inputStream中的内容拷贝到outputStream中：

```java
InputStream in = new FileInputStream("d:/aaa.txt");
OutputStream out = new FileOutputStream("d:/bbb.txt");
in.transferTo(out);
```

### 创建只读集合的方法

```java
// java9之前
// 使用Arrays.asList
List<Integer> list1 = Arrays.asList(1, 2, 3);
// 使用Collections 将非只读集合变为只读集合
list = Collections.unmodifiableCollection(list);

// java9创建只读集合
List.of(1, 2, 3);
Set.of(1, 2, 3);
Map.of(k1, v1, k2, v2, ...);
```

## JShell

可以运行java片段的shell窗口。支持的主要命令：

1. `/list` 列出执行的所有片段
2. `/imports` 列出已经导入的包
3. `/edit` 编辑所有片段
4. `/open 文件地址` 调用本地的某个java脚本
5. `/exit`

## 模块化

谈到Java9大家往往第一个想到的就是Jigsaw项目（后改名为Modularity）。众所周知，Java已经发展超过20年(95年最初发布)，Java和相关生态在不断丰富的同时也越来越暴露出一些问题:

1. Java运行环境的膨胀和臃肿。**每次JVM启动的时候，至少会有30\~ 60MB的内存加载，主要原因是JVM需要加载rt.jar**,不管其中的类是否被classloader加载，第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)
2. 当代码库越来越大，创建复杂，盘根错节的“意大利面条式代码”的几率呈指数级的增长。不同版本的类库交叉依赖导致让人头疼的问题，这些都阻碍了Java 开发和运行效率的提升。
3. 很难真正地对代码进行封装,而系统并没有对不同部分(也就是JAR文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到，这样就会导致无意中使用了并不想被公开访问的API.

什么是模块化：

1. 模块化是在package外的新的一层，一个src目录只能声明为一个模块
2. 在src根目录建立 `module-info.java`，声明module
3. 模块之间的可访问性是所使用的模块和使用模块之间的双向协议，在该文件中可以声明当前模块的依赖，以及当前模块暴露的包

### IDEA Jdk9 模块化工程

定义service模块：

```java
module service {
    // Service 暴露接口包
    exports com.yangsx95.api;
    
    // 依赖java的sql包
    requires java.sql;
}
```

定义api模块，依赖service模块：

```java
module api {
    // 暴露api包下的所有类，但是不包括子包，比如`com.yangsx95.api.impl`包
    exports com.yangsx95.api;

    // 依赖service模块
    requires service;
}
```

### Maven + Jdk9 模块化工程

Maven 本身对模块化的支持已经非常好了，引入java模块化，主要是对包中的类进一步进行访问权限控制。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/programming-language/java/java-te-xing/java9-te-xing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
