接口中允许添加私有方法

java 8 中添加了 default 方法,但这些方法之间却无法优雅的复用代码。例如:methodAmethodB 都需要调用 biFunction 方法,于是只能将 biFunction 方法声明成 default

public interface Java8Interface {
    default void methodA(int a, int b) {
        // do something
        biFunction(a, b);
    }
 
    default void methodB(String a, String b) {
        // do something
        biFunction(a, b);
    }
 
    default void biFunction(Object a, Object b) {
        // do something
    }
}

声明一个新的 default 方法当然可行,但却不符合接口的原则。将不必要的方法,暴露出去会给调用者带来困扰。

public interface Java9Interface {
    default void methodA(int a, int b) {
        // do something
        biFunction(a, b);
    }
 
    default void methodB(String a, String b) {
        // do something
        biFunction(a, b);
    }
 
    private void biFunction(Object a, Object b) {
        // do something
    }
}

允许私有方法后,只需把原来的 default 改成 private 即可。

try-with-resource 优化

Java 7 之前关闭资源需要写如下代码:

BufferedReader br = new BufferedReader(...);
try {
    return br.readLine();
} finally {
    if (br != null) {
        br.close();
    }
}

Java 7 之后引入了 try-with-resource ,简化了 finally 块的代码,现在只需这样:

try (BufferedReader br = new BufferedReader(...)) {
    return br.readLine();
}

但是需要使用的资源一多,代码就会变成这样:

try (BufferedReader br1 = new BufferedReader(...);
    BufferedReader br2 = new BufferedReader(...);
    BufferedReader br3 = new BufferedReader(...)) {
    return br1.readLine() + br2.readLine() + br3.readLine();
}

Java 9 之后:

BufferedReader br1 = new BufferedReader(...);
BufferedReader br2 = new BufferedReader(...);
BufferedReader br3 = new BufferedReader(...);
try (br1; br2; br3) {
    return br1.readLine() + br2.readLine() + br3.readLine();
}

注意:变量声明在 try 外面,很容易误导用户在 try 语句结束后,仍调用资源,这会导致运行时产生错误。

BufferedReader br1 = new BufferedReader(...);
try (br1) {
    System.out.println(br1.readLine());
}
br1.readLine(); // 此时资源已关闭,调用会报错

_ 不再是有效标识符

Java 9 之前可以将 _ 下划线设置为变量,虽然编译器会警告,但运行不会报错。

int _ = 123;
System.out.println(_);

Java 9 之后,代码会编译失败,会得到如下提示:

java: 从发行版 9 开始, '_' 为关键字, 不能用作标识符

菱形符号

Java 7 引入了菱形符号 <>,让编译推断构造器参数类型。

// java 7 之前
List<String> names = new ArrayList<String>();
 
// java 7 之后
List<String> names = new ArrayList<>();

自动参数类型推断,简化了代码。但是匿名内部类的参数推断,却不支持。

这段代码在 Java 7 中,编译器会报错。Java 9 支持匿名内部类的类型推断,代码能正确执行。

<T> Result<T> create(T content) {
    return new Result<>(content) {
      // 实现方法
    };
}