JDK 9新特性 系统模块化 接口私有方法等

JDK9 新特性  

最重要的就是支持模块化编程,和接口私有方法

 

例子中提供服务的 module-info.java 文件   项目A 

/**
 *
 * 1 一个项目,或者说一个jar包只能被属于一个模块,
 * 2 如果没有配置模块就是全部使用(没有配置包含2种,引用方和被引用方)
 * 3 使用模块相当于值暴露一部分需要对外提供服务的类,没有暴露的类不可见(我有两个包,A,B,但是值暴露A,那么引用方如果也使用模块化管理,就只能看到A,看不到B)
 * 4 jdk9 以后 所有的  java jar包前面都爆了一层 moduleName
 * 5 可以认为模块是 一个jar包下面,一组对外暴露服务的包 的别名
 * 6 一般模块的命名就是 这些包的公共前缀,或者公共前缀+能代表这些包的一个名字
 *
 * @author ZHANGYUKUN
 * @date 2022/6/16
 */
module com.lomi.jdkOne {
    exports com.lomi.jdk9One1;
}

  

 

 

例子中引用上面服务(项目A ) jar的另外一个服务(项目B)的module-info.java 文件(maven 中已经导入 项目A的 jar包)

/**
 *
 * 1 如果一个项目引用了一个jar,但是自身没有配置module-info.java,那么相当于使用了这个jar 的全部类
 * 2 如果一个项目引用了一个jar,但是自身配置module-info.java,那么必须在导入了这个 jar的 模块名才能使用里面的 暴露服务类
 *
 * @author ZHANGYUKUN
 * @date 2022/6/16
 */
module com.lomi.jdkTwo {
    requires com.lomi.jdkOne;
}

  

项目结构如下:

 

 

 

测试代码如下:

package com.lomi.jdkTwo1;

import com.lomi.jdk9One1.Goods;
import com.lomi.jdk9One2.Book;
import org.junit.Test;

import java.io.*;
import java.util.*;
import java.util.stream.Stream;

/**
 * @author ZHANGYUKUN
 * @date 2022/6/16
 */
public class JDK9NewTest1 {


    /**
     * 使用模块,相当于在package 上面 多了一层,如果在classpath 根目录有了 module-info.java 文件,那么引用的jar包就不是全部使用,而需要在 module-info.java 里面声明使用
     */
    @Test
    public void test1(){
        //Goods的包被暴露出来可以倍使用(如果不导入模块,就使用,是不能编译通过,除非当前工程不使用模块化管理)
        //模块化管理是相互的,需要 引用方和被引用方都 使用模块化管理才有效
        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.getGoodsList().add( new Goods() );


        //Book的包没有被暴露出来,不能使用(但是目前版本的编译并不会保存,估计后面版本会优化),下面的代码允许会抛出异常
        //Book book = new Book();

        System.out.println(  shoppingCart );


    }

    /**
     * 匿名内部类前面使用<>不会报错,之前java8会报错
     */
    @Test
    public void test2(){

        //java8 只能这样写
        Comparator<Object> comparator2 = new Comparator<Object>() {

            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };

        //java8 这样写会报错
        Comparator<Object> comparator = new Comparator<>() {

            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };
    }



    /**
     *  对try 自动关闭资源的优化,可以使用try外部定义的AutoCloseable资源
     */
    @Test
    public void test3() throws IOException {
        //jdk8以前
        FileWriter fw = null;
        try{
            fw = new FileWriter("C:\\Users\\ZHANGYUKUN\\Desktop\\a.txt");
            fw.write("aaaa");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if( fw != null ){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


        //jdk8,要求资源的申明和赋值都必须在 try的括号内
        try (
                FileWriter fw2 = new FileWriter("C:\\Users\\ZHANGYUKUN\\Desktop\\b.txt");
                FileWriter fw3 = new FileWriter("C:\\Users\\ZHANGYUKUN\\Desktop\\b.txt");
        ){

            fw2.write("bbbb");
            fw3.write("cccc");
        }catch (Exception e){
            e.printStackTrace();
        }

        //jdk9,允许关闭的资源在外面申明并且赋值(不允许在外面申明,try()内赋值)
        FileWriter fw5 = new FileWriter("C:\\Users\\ZHANGYUKUN\\Desktop\\b.txt");
        try (
                FileWriter fw4 = new FileWriter("C:\\Users\\ZHANGYUKUN\\Desktop\\b.txt");
                fw5
                ){
            fw4.write("eeee");
            fw5.write("ffff");
        }catch (Exception e){
            e.printStackTrace();
        }


        //不管那种try()的优化实际上在 try 方法体内部都使用的一个静态指针(这个资源在 try{} 里面是不能修改的,相当于一个常量),并且这个静态指针作用范围只有 try 结束就自动释放了

        //自动关闭的资源需要实现 AutoCloseable 接口


        System.out.println("end---------");
    }



    /**
     *  String 类型 以前使用char 数组,现在用的 byte数组(可以省空间)(StringBuilder ,StringBuffer 也是换成byte数组了,正常我们应该用StringBuilder,而不是StringBuffer)
     */
    @Test
    public void test4() throws IOException {
        //char 是2 个字节,byte 是一个字节,jvm 内部的 编码是 UTF-16或者是定长2字节的UES2,现在才是动长的 UTF-16(短的用1个字节,长的用2个字节,2个字节转不下的用4个字节)
        //这样做的原因是大多数时候程序的字符串都是 ASCII 编码可以表示的(一个字节就够了),全都用2个字节太浪费内存

    }


    /**
     *  只读集合的工厂方法
     *  三大集合 提供了of方法,没有jdk8 允许了接口的静态方法,所以现在 of的工厂方法都由 三大集合接口提供,而不是 Collections 提供
     */
    @Test
    public void test5() throws IOException {
        //这个方式创建的定长集合,依旧可以修改
        List<Integer> readOnlyList = Arrays.asList(1, 2, 3,null);
        readOnlyList.set(0,100);
        System.out.println( readOnlyList.get(0) );


        //以前创建只读集合
        Map<String, String> readOnlyMap = Collections.unmodifiableMap(new HashMap<String, String>());



        //jdk9写法(List.Set,Map都有类似的方法),为啥作者要把同样的方法写10 次?
        Set<Integer> set = Set.of(1, 2);
        Map.ofEntries( Map.entry("key","value") );

    }

    /**
     *  直接把 输入流 对接到输出流(自带8K缓冲区),怎么获取路径?
     *  输入流,提供 transferTo 方法
     */
    @Test
    public void test6() throws IOException {

        try(
                InputStream inputStream = JDK9NewTest1.class.getClassLoader().getResourceAsStream("a.txt");
                FileOutputStream outputStream = new FileOutputStream( "b.txt"  );
        ){

           inputStream.transferTo(outputStream);

        }catch (Exception e){

        }

    }


    /**
     * stream api 新增了4个方法takeWhile,dropWhile,ofNullable,自带退出条件的iterate
     */
    @Test
    public void test7() throws IOException {

        //takeWhile(第一个不满足条件一户的都会删除)
        System.out.println( Stream.of(1, 2, 3, 4, 5, 6, 7, 8).takeWhile(item -> (item < 3)).toArray().length );
        System.out.println("---------------------------------------------------------------");
        //dropWhile(第一个不满足条件之前的都会删除)
        System.out.println( Stream.of(1, 2, 3, 4, 5, 6, 7, 8).dropWhile(item -> (item < 3)).toArray().length );

        System.out.println("---------------------------------------------------------------");

        //以前的Stream.of(null),是不允许的。jdk9 Stream.ofNullable(null) 允许空
        Stream.ofNullable(null);
        Stream.of(null,null);
        //Stream.of(null);

        //iterate 自带退出条件
        Stream.iterate( 0,item->item<100,item->item+1 ).forEach(System.out::println);



    }


    /**
     *  Optional 的一些新方法 ifPresentOrElse(),or(),stream()
     */
    @Test
    public void test8() throws IOException {

        //Optional.or 空值的时候返回 一个默认的 Optional
        String value = null;
        Optional optional =  Optional.ofNullable( value );
        optional = optional.or( ()-> Optional.of("默认值")  );
       // System.out.println("结果:" + optional.get() );


        //不为空调用方法A,为空调用方法2( 和  optional.orElseThrow() 类似 )
        optional.ifPresentOrElse(System.out::println,()->{
            System.out.println("是空");
        });






        //jdk8有的方法,和 orElse 的加强版
        optional.orElseGet( ()->"默认值" );


        //平铺的optional(其实也没有平铺,重点在map Optional )
        List<String> list = null;
        Optional<String> s = Optional.ofNullable(list).flatMap(item -> Optional.of(item.get(0)));

    }

    /**
     * 私有方法
     */
    @Test
    public void test9(){
        Impl1 impl1 = new Impl1();
        Impl2 impl2 = new Impl2();

        impl1.methodDefault();
        impl1.methodNotmal();

        //接口的静态方法只能通过接口名字调用,不能通过实例对象调用
        Interface1.methodStatic();

        //私有方法只能自己调用
        //impl1.methodProvide();


    }


    /**
     *  nashorn 引擎
     */
    @Test
    public void test10() throws IOException {

        //后面的jdk版本删除了,没继续了解
    }


}

  

 

posted on 2022-06-17 20:00  zhangyukun  阅读(158)  评论(0编辑  收藏  举报

导航