Hello! Java 9


  java9正式发布已经有一段时间了,作为一个思想激进__开放__,勇于探索的喵,本着拥抱新特性的心态。第一时间对java的文档进行了拜读,结合这段时间零零散散__持续__的测试和理解,记录下来以后可能会用到的几个特性。

JShell

Java 9 中引入了交互式编程环境(REPL),这就是JShell。JShell可以执行Java代码,并且立即返回执行结果。可以用来测试一些简单的方法,函数以及算法。本喵或许可以告别创建一个Text.java然后写一个main方法来测试一些函数的做法,使用JShell可以快速地执行代码,节省了项目编译的时间。付出的代价就是需要多多练习脱离IDE码代码的技能了。
使用方法:安装好Java9并配置好运行环境后,在命令行输入

BOBOdeRMBP:~ bobo$ java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)
BOBOdeRMBP:~ bobo$ jshell 
|  欢迎使用 JShell -- 版本 9
|  要大致了解该版本, 请键入: /help intro

jshell> 

即可进入JShell。
测试一下基本功能。声明一个int类型的变量,并未这个变量赋值。然后打印出变量信息。

jshell> int i = 10
i ==> 10

jshell> System.out.print("i:"+i)
i:10
jshell> 
查看更多介绍。。。

不可变集合类的工厂方法

在处理多线程操作数据时,大多数时候数据线程安全和脏数据问题都会被掩盖。在Java8以及更早版本,我们创建一个不可变集合对象时通常使用Collections.unmodifiableXXX的方法。当我们需要初始化这样一个不可变集合的时候就显得比较麻烦了。
在Java9中,Oracle引用了一些非常方便的工厂方法可以用来创建各种不可变集合。

//空list 9 befor
List emptylist = Collections.EMPTY_LIST;
//空list 9
List emptylist9 = List.of();

//非空list 9 befor
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
List notEmptylist = Collections.unmodifiableList(list);
//非空list 9
List<String> notEmptylist9 = List.of("a", "b", "c", "d", "e");

//空map 9 befor
Map emptyMap = Collections.EMPTY_MAP;
//空map 9
Map emptyMap9 = Map.of();

//非空map 9 befor
Map<String, String> map = new HashMap<>();
map.put("a", "this is a");
map.put("b", "this is b");
map.put("c", "this is c");
map.put("d", "this is d");
Map<String, String> notEmptyMap = Collections.unmodifiableMap(map);
//非空map 9
Map<String, String> map1 = Map.of("a", "this is a", "b", "this is b", "c", "this is c", "d", "this is d");//这种写法最大支持10个键值对
Map<String, String> map2 = Map.ofEntries(Map.entry("a", "this is a"), Map.entry("b", "this is b"), Map.entry("c", "this is c"), Map.entry("d", "this is d"));
    
//set略

接口的私有方法

在Java8中,接口中可以定义模式实现和静态方法。但是不能创建私有方法。为了避免冗余代码和提高重用性,Java9现在支持定义私有方法,声明使用的方式与普通类中的一致。进一步提高代码复用率。举个🌰

//Dog.java 
public interface Dog {
    static void barking() {
        System.out.println("汪汪汪");
    }

    private static void cry() {
        System.out.println("呜呜呜");
    }

    default void sad() {
        cry();
    }

    void play();

}
//Husky.java
public class Husky implements Dog {
    @Override
    public void sad() {
        System.out.println("我不哭,我拆家");
    }

    @Override
    public void play() {
        Dog.barking();
        System.out.println("不管怎么样都疯狂撒欢");
    }

}
//GoldenRetriever.java
public class GoldenRetriever implements Dog {
    @Override
    public void play() {
        System.out.println("不管怎么样都非常开心");
        Dog.barking();
    }
}

//main.java

public static void main(String[] args) {
        Husky husky = new Husky();
        husky.sad();
        husky.play();
        GoldenRetriever goldenRetriever = new GoldenRetriever();
        goldenRetriever.sad();
        goldenRetriever.play();


    }

1.定义Dog接口抽象狗子们的行为。抽象的结果:所有狗子需要玩(play)但是表现不一样。所有狗子都会叫(barking)而且都是“汪汪汪”。
狗子们会伤心(sad),大部分狗子伤心都会哭(cry),个别例外。
2.具体实现狗子,先实现二哈Husky。二哈伤心的时候是例外,独立实现了伤心的方法。play的实现是撒欢,并且像所有狗子一样叫。然后实现金毛GoldenRetriever。金毛伤心时和大部分狗子一样会哭。play的实现是开心,并且像所有狗子一样叫。
叫(barking)是所有对象共有的特征,抽象成接口的静态方法,允许所有的实现内部调用。
伤心(sad)是大部分对象的共同特征,可以在接口抽象出默认实现,个例独立实现。
哭泣(cry)是内部接口抽取的公共代码,会被伤心(sad)等其它接口内部方法调用。

Java9的接口允许定义

支持 是否可外部引用 是否可实现/重写
常量变量
抽象的方法 ❌¿
默认的方法
静态方法
私有方法
私有静态方法

Stream增强

Stream作为Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全不同的概念。它也不同于StAX对XML解析的Stream,也不是AmazonKinesis对大数据实时处理的Stream。Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregateoperation),或者大批量数据操作(bulkdataoperation)。StreamAPI借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错,但使用StreamAPI无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java8中首次出现的java.util.stream是一个函数式语言+多核时代综合影响的产物

以上摘自ibm developerworks

Java9对Stream操作又进行了进一步强化。Stream接口中添加了4个新的方法:dropWhile,takeWhile,ofNullable。还有个iterate方法的新重载方法。
iterate的重载方法方法提供了一个Predicate来指定什么时候结束,在Java8中,使用limit方法来约束iterate返回的Stream的长度。下面是三段等价代码

Stream.iterate(1, i -> i < 200, i -> i + 2).forEach(System.out::println);
Stream.iterate(1, i -> i + 2).limit(100).forEach(System.out::println);
for (int i = 1; i < 200; i += 2) {
    System.out.println(i);
}

dropWhile和takeWhile,废话不多说,直接上代码

List<Integer> list = new ArrayList<>();
Stream.iterate(1, i -> i < 10, i -> i + 1).forEach(list::add);
Stream.iterate(1, i -> i < 10, i -> i + 1).forEach(list::add);
list.forEach(System.out::print);
System.out.println();
list.stream().dropWhile(s -> s < 5).forEach(System.out::print);
System.out.println();
list.stream().takeWhile(s -> s < 5).forEach(System.out::print);

//输出结果
// 123456789123456789
// 56789123456789
// 1234

dropWhile和takeWhile和filter方法相似但不相同。
filter方法验证Stream中的每一个元素。
dropWhile方法对于有序流,从断言指定为true的起始处丢弃元素。当输出条件为小于5时返回true,使用dropWhile会删除前4个元素。对于无序流dropWhile方法的行为是非确定性的。它可以选择删除匹配条件的任何元素子集。当前的实现从匹配元素开始丢弃匹配元素,直到找到不匹配的元素。dropWhile方法有两种极端情况。如果第一个元素与predicate不匹配,则该方法返回原始流。如果所有元素与predicate匹配,则该方法返回一个空流。
takeWhile方法的工作方式与dropWhile方法相同,只不过它从流的起始处返回匹配的元素,而丢弃其余的。

Java8中Stream不能包含null,否则会报空指针异常,而Java9中的ofNullable方法允许我们创建一个单元素Stream,可以包含一个非空元素,也可以创建一个空Stream。

Stream<String> stream = Stream.ofNullable("hello,world");
System.out.println(stream.count());
//jshell 执行结果 1
stream = Stream.ofNullable(null);
System.out.println(stream.count());
//jshell 执行结果 0

改进应用安全性能

Java9新增了4个SHA-3哈希算法,SHA3-224、SHA3-256、SHA3-384和SHA3-512。另外也增加了通过java.security.SecureRandom生成使用DRBG算法的强随机数。

final MessageDigest instance = MessageDigest.getInstance("SHA3-224"); 
final byte[] digest = instance.digest("".getBytes()); 
System.out.println(Hex.encodeHexString(digest));

进程API

Java9增加了ProcessHandle接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程。在使用ProcessBuilder来启动一个进程之后,可以通过Process.toHandle()方法来得到一个ProcessHandle对象的实例。通过ProcessHandle可以获取到由ProcessHandle.Info表示的进程的基本信息,如命令行参数、可执行文件路径和启动时间等。ProcessHandle的onExit()方法返回一个CompletableFuture对象,可以在进程结束时执行自定义的动作。代码清单8中给出了进程API的使用示例。

final ProcessBuilder processBuilder = new ProcessBuilder("top") 
    .inheritIO(); 
final ProcessHandle processHandle = processBuilder.start().toHandle(); 
processHandle.onExit().whenCompleteAsync((handle, throwable) -> { 
    if (throwable == null) { 
        System.out.println(handle.pid()); 
    } else { 
        throwable.printStackTrace(); 
    } 
});

以上简单说一下Java9中语法的新特性,Java9的特性还包括Project Jigsaw(平台模块系统),http 2,I/O流新特性等等。后面本喵会逐步理解分析Java9中优秀的概念设计,希望能尽快享受Java9带来的工作便利。


文章作者: 鱍鱍
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 鱍鱍 !
 上一篇
JShell JShell
jshell是Java9新增的一个实用工具。jshell为Java增加了类似NodeJS和Python中的读取-求值-打印循环(Read-Evaluation-PrintLoop)。在jshell中可以直接输入表达式并查看其执行结果。当需
2018-02-06
下一篇 
Vertx的Hello World! Vertx的Hello World!
由于Vert.x目前“火爆”的人气,使用各种搜索引擎都能找到大量的社区网站、博客来介绍vertx各种概念。这里就不再啰嗦了。本喵从今天开始,使用实际的代码来展示实际工作中可能会遇到的一些问题。以及解决方案。如果你有在使用Vert.x,并且遇
  目录