Java 9 10 11 新特性 (9—>模块化 创建只读集合of 输入流transferTo stream API增加方法 10—>var 只读集合copyOf 11—> isEmpty())

  • Java8-11的变更概述

  • 经过4次跳票,历经曲折的Java 9 终于终于在2017年9月21日发布。
  • 从Java 9 这个版本开始,Java 的计划发布周期是6个月,下一个 Java 的主版本将于2018年3月发布,命名为 Java 18.3,紧接着再过六个月将发布 Java 18.9。
  • 这意味着Java的更新从传统的以特性驱动的发布周期,转变为以时间驱动的 (6 个月为周期)发布模式,并逐步的将 Oracle JDK 原商业特性进行开源。
  • 针对企业客户的需求,Oracle 将以三年为周期发布长期支持版本(long term support)
  • Java 9 提供了超过150项新功能特性,包括备受期待的模块化系统、可交互的 REPL 工具:jshell,JDK 编译工具,Java 公共 API 和私有代码,以及安全增强、扩展提升、性能管理改善等。可以说Java 9是一个庞大的系统工程, 完全做了一个整体改变。
  • Java 9新特性

新特性列举 

相关资料参考

官方提供的新特性列表: https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUIDC23AFD78-C777-460B-8ACE-58BE5EA681F 

或参考 Open JDK http://openjdk.java.net/projects/jdk9/

在线Oracle JDK 9 Documentation https://docs.oracle.com/javase/9/

 新特性1——接口的私有方法

概述

  • Java 8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是 一个抽象类。
  • 在Java 9中,接口更加的灵活和强大,连方法的访问权限修饰符都可 以声明为private的了,此时方法将不会成为你对外暴露的API的一部分。 

代码演示

定义有私有方法的接口

public interface MyInterface {
    void methodShow();

    static void methodStatic(){
        System.out.println("接口静态方法");
    }

    default void methodDefault(){
        System.out.println("接口的默认方法");
    }

    //java9之后可以在接口中定义私有方法
    private void methodPrivate(){
        System.out.println("接口的默认方法");
    }
}

 接口的实现类

public class PrivateInterfaceTest implements MyInterface{

    @Override
    public void methodShow() {
        MyInterface.super.methodDefault();
    }

    @Override
    public void methodDefault() {
        System.out.println("实现类重写了接口中的默认方法");
    }

    public static void main(String[] args) {
        //接口中的静态方法只能由接口自己调用
        MyInterface.methodStatic();
        PrivateInterfaceTest pit = new PrivateInterfaceTest();
        //接口的实现类不能调用接口的静态方法
        //pit.methodStatic();
        pit.methodDefault();
        pit.methodShow();
        //接口的私有方法,不能在接口外部调用
        //pit.methodPrivate();
    }
}

 特性2——钻石操作符使用升级

概述

  • Java 7的新特性——类型推断,方便了我们在创建类的对象时,只用在前一个类后声明对应泛型即可。eg: ArrayList<String> list = new ArrayList<>();
  • 但是对于匿名内部类还是不支持的,因此Java 9对应做了升级,优化了该问题。

代码演示

@Test
public void test1(){
    Comparator<Integer> com = new Comparator<>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return 0;
        }
    };
}

 新特性3——try语句改进

概述

  • Java 1.8之前为了一定可以执行资源的关闭,我们需要将关闭的资源操作写在try语句的finally中
  • Java 8 时,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。
  • Java 9 又做了写改变,用资源语句编写try将更容易,我们可以在try子句中使用已经初始 化过的资源,此时的资源是final的。

代码演示

public class Java9Test {
    public static void main(String[] args) {
        //Java1.8之前的写法
        /*InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(System.in);
            char[] bbuf = new char[20];
            int len;
            if ((len = isr.read(bbuf)) != -1){
                String str = new String(bbuf,0,len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (isr != null)
                isr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }*/

        //Java1.8的写法
        /*try(InputStreamReader isr1 = new InputStreamReader(System.in)) {
            char[] bbuf1 = new char[20];
            int len;
            if ((len = isr1.read(bbuf1)) != -1){
                String str1 = new String(bbuf1,0,len);
                System.out.println(str1);
            }
        }catch (IOException e){
            e.printStackTrace();
        }*/

        //Java1.9的写法
        InputStreamReader isr2 = new InputStreamReader(System.in);
        OutputStreamWriter osw2 = new OutputStreamWriter(System.out);
        try (isr2; osw2) {
            char[] bbuf2 = new char[20];
            int len;
            if ((len = isr2.read(bbuf2)) != -1) {
                osw2.write(bbuf2, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

新特性4——String存储结构变更

String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约 了一些空间。

新特性5——集合工厂方法:快速创建只读集合 

Java8及之前创建只读集合的写法

//方式1:
@Test
public void test2(){
    List<String> list = new ArrayList<>();
    list.add("Jane");
    list.add("Make");
    list.add("Tom");

    list = Collections.unmodifiableList(list);
    //list.add("Jerry");//仅为可读集合,不可再次添加元素
    System.out.println(list);
}

//方式2:
Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("aa", "bb", "cc")));
set.forEach(v -> System.out.println(v));

//方式3:
Set<String> set1 = Collections.unmodifiableSet(new HashSet<String>() {
    {
        add("aa");
        add("bb");
        add("cc");
    }
});
set1.forEach(v -> System.out.println(v));

通过Arrays.asList()方法得到的集合也是一个只读集合

@Test
public void test4(){
    List<String> list = Arrays.asList("aa", "bb", "cc");
    //list.add("dd");//不允许再次添加
    list.forEach(s -> System.out.println(s));//aa bb cc
    System.out.println(list);//[aa, bb, cc]
}

Java9及之后创建只读集合的写法

@Test
public void test5(){
    Map<String, Integer> map = Map.of("Tom", 23, "Jane", 24, "Jerry", 25);
    //map.put("Make",26);//不允许再次添加
    System.out.println(map);

    Map<String, Integer> map1 = Map.ofEntries(Map.entry("aa", 11), Map.entry("bb",22));
    //map1.put("cc",22);//不允许再次添加
    System.out.println(map1);
}

 新特性6——InputStream 加强

 新增:transferTo()方法,可以用来将数据直接 传输到 OutputStream,这是在处理原始数据流时非常常见的一种用法

@Test
public void test6(){
    ClassLoader classLoader = this.getClass().getClassLoader();
    try(InputStream is = classLoader.getResourceAsStream("day12\\data.txt");
        OutputStream os = new FileOutputStream("src\\day12\\data1.txt")){
        // 把输入流中的所有数据直接自动地复制到输出流中
        is.transferTo(os);
    }catch (IOException e){
        e.printStackTrace();
    }
}

新特性7——增强的 Stream API

  • Java 的 Steam API 是java标准库最好的改进之一,让开发者能够快速运算, 从而能够有效的利用数据并行计算。Java 8 提供的 Steam 能够利用多核架构 实现声明式的数据处理。
  • 在 Java 9 中,Stream API 变得更好,Stream 接口中添加了 4 个新的方法: takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以 让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
  • 除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。 现在可以通过 Optional 的新方法 stream() 将一个 Optional 对象转换为一个 (可能是空的) Stream 对象。 

新增的四个方法代码演示

  • takeWhile()用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的 Stream 中,takeWhile 返回从开头开始的尽量多的元素。
  • dropWhile()方法的行为与 takeWhile 相反,返回剩余的元素。 
@Test
public void test1(){
    List<Integer> list = Arrays.asList(11, 22, 12, 88, 3, 54);
    //takeWhile 返回从开头开始的按照指定规则尽量多的元素
    list.stream().takeWhile(s -> s < 30).forEach(System.out::println);//11 22 12
    //dropWhile():与 takeWhile 相反,返回剩余的元素。
    list.stream().dropWhile(s -> s < 30).forEach(System.out::println);//88 3 54
}
  •  ofNullable()的使用:Java 8 中 Stream 不能完全为null,否则会报空指针异常。而 Java 9 中的 ofNullable 方 法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空 Stream。
@Test
public void test2(){
    //of()参数中的多个元素,可以包含null值
    Stream<? extends Serializable> stream = Stream.of(11, 22, 33, null, "ss");
    stream.forEach(System.out::println);
    //of()参数不能存储单个null值。否则,报异常
    /*Stream<Object> stream1 = Stream.of(null);
    stream1.forEach(System.out::println);*/

    //Java 9新特性ofNullable():形参变量是可以为null值的单个元素
    Stream<Object> stream2 = Stream.ofNullable(null);
    long count = stream2.count();
    System.out.println(count);//0
}
  •  iterate()重载的使用:这个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什 么时候结束迭代。
@Test
public void test3(){
    Stream.iterate(0,x -> x+1).limit(10).forEach(System.out::println);
    //java9中新增的重载的方法
    Stream.iterate(0,x -> x < 100,x -> x+1).forEach(System.out::println);
}

 新特性8——增加Optional获取Stream的方法

Optional.stream();

@Test
    public void test4(){
        List<String> list = new ArrayList<>();
        list.add("Tom");
        list.add("Jane");
        list.add("Jerry");

        Optional<List<String>> listOptional = Optional.ofNullable(list);
        Stream<List<String>> stream = listOptional.stream();
        //System.out.println(stream.count());//1
        stream.flatMap(new Function<List<String>, Stream<?>>() {
            @Override
            public Stream<?> apply(List<String> list) {
                return list.stream();
            }
        }).forEach(System.out::println);//Tom Jane Jerry
    }
  • Java 10新特性

概述

  • 2018年3月21日,Oracle官方宣布Java10正式发布。
  • 需要注意的是 Java 9 和 Java 10 都不是 LTS (Long-Term-Support) 版本。和过去的 Java 大版本升级不同,这两个只有半年左右的开发和维护期。而之后的 Java 11,也就是 18.9 LTS,才是 Java 8 之后第一个 LTS 版本。
  • JDK10一共定义了109个新特性,其中包含12个JEP(对于程序员来讲,真 正的新特性其实就一个_Local-Variable Type Inference 局部变量类型推断),还有一些新API和JVM规范以及JAVA语言规范上 的改动。
  • JDK10的12个JEP(JDK Enhancement Proposal特性加强提议)参阅官方文档:http://openjdk.java.net/projects/jdk/10/

新特性1——局部变量类型推断

概述

解决的痛点

开发者经常抱怨Java中引用代码的程度。局部变量的显示类型声明,常常被认为 是不必须的,给一个好听的名字经常可以很清楚的表达出下面应该怎样继续。这样减少了啰嗦和形式的代码,避免了信息冗余,而且对齐了变量名,更容易阅读! 

工作原理

在处理 var时,编译器先是查看表达式右边部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中。 

注意事项

var不是一个关键字,你不需要担心变量名或方法名会与 var发生冲突,因为 var实际上并不是一个关键字, 而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。除此之外,它就是一个普通合法的标识符。也就是说,除了不能用它作为类名,其他的都可以, 但极少人会用它作为类名。

这不是JavaScript,首先我要说明的是,var并不会改变Java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。事实上,这一特性只发生在编译阶段,与运行时无关,所以对运行时的性能不会产生任何影响。所 以请放心,这不是 JavaScript。

适用于使用局部变量类型推测的创景

  •  情况1:声明变量时,根据所附的值,推断变量的类型 
    var name = "嘻戏";
    var list = new ArrayList<>();
  •  情况2:遍历操作——增强for循环
    var list = new ArrayList<>();
    list.add("Tom");
    list.add("Jerry");
    for (var v : list) {
        System.out.println(v);
    }
  • 情况3:遍历操作——普通for循环
    for (var i = 0; i < 10; i++) {
        System.out.println(i);
    }

 在局部变量中使用时,如下情况不适用

  • 情况1:局部变量不赋值,就不能实现类型推断 
    var name;
  • 情况2:lambda表示式中,左边的函数式接口不能声明为var
    Consumer<String> com = (s) -> System.out.println(s);
    //var com1 = (s) -> System.out.println(s);
  • 情况3:方法引用中,左边的函数式接口不能声明为var
    Supplier<Double> sup = Math::random;
    //var sup1 = Math::random;
  • 情况4:数组的静态初始化中,注意如下的情况也不可以
    int[] arr = new int[]{11,22,33};
    var arr1 = new int[]{11,22,33};
    //var arr2 = {11,22,33};

 在局部变量中使用时,如下结构不适用 

  •  情况1:没有初始化的局部变量声明
    @Test
        public void test3(){
            var num = null;
        }
  • 情况2:方法的返回类型
    public var show(String s){
            return s;
        }
  • 情况3:方法的参数类型
    public void show(var s){
            System.out.println(s);
        }
  • 情况4:构造器的参数类型
    public Person(var name,var id){
            this.name = name;
            this.id = id;
        }
  • 情况5:属性
    var num;
  • 情况6:catch块
    try {
       
    } catch (var e) {
        e.printStackTrace();
    }

 新特性2——新增加创建只读集合方法(copyOf)

概述

自 Java 9 开始,Jdk 里面为集合(List / Set / Map)都添加了 of (jdk9新增)和 copyOf (jdk10新增)方法,它们两个都用来创建不可变的集合 

copyOf(Xxx coll):如果参数coll本身就是一个只读集合,则copyOf()返回值即为当前的coll,如果参数coll不是一个只读集合,则copyOf()返回一个新的集合,这个集合是只读的。

@Test
public void test3(){
    var list1 = List.of("aa","bb","cc");
    var list2 = List.copyOf(list1);
    System.out.println(list1 == list2);//true

    var list3 = new ArrayList<String>();
    List<String> list4 = List.copyOf(list3);
    System.out.println(list3 == list4);//false
}
  • Java 11新特性

概述

  • 2018年9 月 26 日, Oracle 官方宣布 Java 11 正式发 布。 该版本为长期支持版本(LTS, Long-Term-Support)。
  • Java 11 不仅提供 了长期支持服务,还将作为 Java 平台的参考实现。 Oracle 直到2023年9月都会为 Java 11 提供技术支持,而补 丁和安全警告等扩展支持将持续到2026年。
  • Java11 将带来 ZGC、 Http Client 等重要特性,一共包 含 17 个 JEP(JDK Enhancement Proposals,JDK 增强提案)。
  • 从 JVM GC 的角度,JDK11 引入了两种新的 GC,其中包括也许是划时代意义 的 ZGC,虽然其目前还是实验特性,但是从能力上来看,这是 JDK 的一个巨大突破,为特定生产环境的苛刻需求提供了一个可能的选择。例如,对部分企业核心存储等产品,如果能够保证不超过 10ms 的 GC 暂停,可靠性会 上一个大的台阶,这是过去我们进行 GC 调优几乎做不到的,是能与不能的问题。

新特性1:String中新增的方法

  • isBlank():判断字符串是否为空白
    System.out.println("".isBlank());//true
    System.out.println("\n".isBlank());//true
    System.out.println("\t".isBlank());//true
  • strip():去除首尾空白
  • stripTrailing():去除尾部空格
  • stripLeading():去除首部空格
    String str = " ***" + " \t abc \t  " + "*** ";
    System.out.println(str);// *** 	 abc 	  *** 
    System.out.println(str.strip());//*** 	 abc 	  ***
    System.out.println(str.trim());//*** 	 abc 	  ***
    System.out.println(str.stripTrailing());// *** 	 abc 	  ***
    System.out.println(str.stripLeading());//*** 	 abc 	  *** 
  • repeat(int count):复制字符串
    String s = "ab";
    System.out.println(s.repeat(3));//ababab
  • lines().count():行数统计 
    String s1 = "ab\n11\n";
    String s2 = "ab\n11\n22";
    System.out.println(s1.lines().count());//2
    System.out.println(s2.lines().count());//3

新特性2:Optional新增的方法 

Optional 也增加了几个非常酷的方法,现在可以很方便的将一个 Optional 转换 成一个 Stream, 或者当一个空 Optional 时给它一个替代的。 

  • boolean isEmpty() 判断value是否为空 (JDK 11新增)
    Optional<Object> empty = Optional.empty();
    System.out.println(empty.isEmpty());//true //判断内部的value是否为空(Java11新增方法)
    System.out.println(empty.isPresent());//false //判断内部的value是否存在
  • T orElseThrow() value非空,返回value;否则抛异常 NoSuchElementException(JDK 10新增)
    var optional = Optional.of("aaa");
    String s = optional.orElseThrow();
    System.out.println(s);
  • ifPresentOrElse​(Consumer action, Runnable emptyAction) value非空,执行参数1功能;如果value 为空,执行参数2功能(JDK 9新增)
    @Test
    public void test4(){
        Optional<String> optional = Optional.of("111");//非空执行参数1的功能
        //Optional<Object> optional = Optional.empty();空执行参数2的功能
        Optional<String> optional1 = Optional.of("aaa");
        Optional<String> optional2 = Optional.of("bbb");
        optional.ifPresentOrElse((s) -> System.out.println(optional1),() -> System.out.println(optional2));
    }
  • Optional or​(Supplier> supplier) value非空,返回对应的Optional; value为空,返回形参封装的Optional(JDK 9新增)
    @Test
    public void test3(){
        var optional = Optional.of("aaa");
        var optional1 = Optional.of("bbb");
        Optional<String> or = optional.or(() -> optional1);
        System.out.println(or);//Optional[aaa]
    
        var optional2 = Optional.empty();
        var optional3 = Optional.of("bbb");
        Optional<Object> or1 = optional2.or(() -> optional3);
        System.out.println(or1);//Optional[bbb]
    }

 新特性3:局部变量类型推断的升级

在var上添加注解的语法格式,在jdk10中是不能实现的。在JDK11中加入了这样的语法。 

//使用var的好处是在使用lambda表达式时给参数加上注解。
Consumer com = (@MyAnnotation var t) -> System.out.println(t.getClass());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值