• 重学JavaSE 第19章 : Java9新特性、Java10新特性、Java11新特性



    Java9新特性

    在这里插入图片描述

    jdk目录结构的改变

    在这里插入图片描述

    bin 目录包含命令行开发和调试工具,如javac,jar和javadoc。
    include目录包含在编译本地代码时使用的C/C++头文件
    lib 目录包含JDK工具的几个JAR和其他类型的文件。它有一个tools.jar文件,其中包含javac编译器的Java类
    jre/bin 目录包含基本命令,如java命令。在Windows平台上,它包含系统的运行时动态链接库(DLL)。
    jre/lib 目录包含用户可编辑的配置文件,如.properties和.policy文件。包含几个JAR。rt.jar文件包含运行时的Java类和资源文件。

    在这里插入图片描述

    没有名为jre的子目录
    bin目录包含所有命令。在Windows平台上,它继续包含系统的运行时动态链接库。
    conf目录包含用户可编辑的配置文件,例如以前位于jre\lib目录中的.properties和.policy文件
    include目录包含要在以前编译本地代码时使用的C/C++头文件。它只存在于JDK中
    jmods目录包含JMOD格式的平台模块。创建自定义运行时映像时需要它。它只存在于JDK中
    legal目录包含法律声明
    lib目录包含非Windows平台上的动态链接本地库。其子目录和文件不应由开发人员直接编辑或使用
    • 新版本jdk的下载与IDEA开发环境的设置

    在这里插入图片描述

    java9新特性:模块化系统

    • 用模块来管理各个package,通过声明某个package暴露,模块(module)的概念,其实就是package外再裹一层,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。

    • 实现目标

      • 模块化的主要目的在于减少内存的开销
      • 只需必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
      • 改进Java SE 平台,使其可以适应不同大小的计算设备
      • 改进其安全性,可维护性,提高性能
    • 模块将由通常的类和新的模块声明文件(module-info.java)组成。该文件是位于java代码结构的顶层,该模块描述符明确地定义了我们的模块需要什么依赖关系,以及哪些模块被外部使用。在exports子句中未提及的所有包默认情况下将封装在模块中,不能在外部使用。

    • 案例结构

    • Person类

    package git;
    
    @Data
    public class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • module-info.java——JDK9Test中
    module JDK9Test {
         exports git;   //exports 包名--》将包暴露使用
    }
    
    • 1
    • 2
    • 3
    • module-info.java——day13中
    module day13 {
        requires JDK9Test;  //requires 包名---》接收包
        requires junit;//若要调用JDK9以上版本的测试类,需要引入
        exports github;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • ModuleTest类
    import git.Person;
    
    public class ModuleTest {
        public static void main(String[] args) {
            Person p = new Person("Jack",20);
            System.out.println(p);
        }
    }
    
    // Person{name='Jack', age=20}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    java9新特性:Java的REPL工具:jshell

    • 产生背景

      像Python和Scala之类的语言早就有交互式编程环境REPL(read-evaluate-print-loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。

    • 设计理念

      • 即写即得、快速运行
    • 实现目标

      • Java 9 中终于拥有了REPL工具:jShell。让Java可以像脚本语言一样运行,从控制台启动jShell,利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行Java的代码,而无需创建Java文件,无需跟人解释”public static void main(String[] args)”这句废话。
      • jShell也可以从文件中加载语句或者将语句保存到文件中。
      • jShell也可以是tab键进行自动补全和自动添加分号。

    jShell 具体使用, 自行了解

    java9新特性:接口中声明私有方法

    • Java8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是一个抽象类。
    • 在Java9中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为private的了此时方法将不会成为你对外暴露的API的一部分
    public interface MyInterface {
    
        //如下的三个方法的权限修饰符都是public
        void methodAbstract();
    
        static void methodStatic(){
            System.out.println("这是接口中的静态方法");
        }
    
        default void methodDefault(){
            System.out.println("这是接口中的默认方法");
            methodPrivate();
        }
    
        //jdk 9中允许接口中定义私有的方法
        private void methodPrivate(){
            System.out.println("这是接口中的私有方法");
        }
    }
    
    public class MyInterfaceImpl implements MyInterface{
    
        @Override
        public void methodAbstract() {
    
        }
    
        @Override
        public void methodDefault() {
            System.out.println("实现类重写了接口中的默认方法");
        }
    
        public static void main(String[] args) {
            //接口中的静态方法只能由接口自己调用
            MyInterface.methodStatic();
            
            // 接口的实现类不能调用接口的静态方法
    		// MyInterfaceImpl.methodStatic();
    
            MyInterfaceImpl impl = new MyInterfaceImpl();
            impl.methodDefault();
            
            // 接口的私有方法,不能在接口外部调用
            // impl.methodPrivate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    java9新特性:钻石操作符的语法升级

    • 我们将能够与匿名实现类共同使用钻石操作符(diamondoperator)在Java8中如下的操作是会报错的
    //java9特性5:钻石操作符的升级
    @Test
    public void test2(){
        //钻石操作符与匿名内部类在java 8中不能共存。在java9可以。
        Comparator<Object> com = new Comparator<>() {
            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };
    
        //jdk7中的新特性:类型推断
        ArrayList<String> list = new ArrayList<>();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 编译报错信息:Cannotuse“<>”with anonymous inner classes.

    java9新特性:try结构的语法升级

    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.Comparator;
    
    public class Java9Test {
    
        // try操作的升级
        public static void main(String[] args) {
            //java 8之前的资源关闭的操作
    //        InputStreamReader reader = null;
    //        try {
    //            reader = new InputStreamReader(System.in);
    //            char[] cbuf = new char[20];
    //            int len;
    //            if((len = reader.read(cbuf) )!= -1){
    //                String str = new String(cbuf,0,len);
    //                System.out.println(str);
    //            }
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        } finally {
    //            if(reader != null){
    //                try {
    //                    reader.close();
    //                } catch (IOException e) {
    //                    e.printStackTrace();
    //                }
    //            }
    //        }
    
            //java 8中资源关闭操作: Java 8 中,可以实现资源的自动关闭
            //要求自动关闭的资源的实例化必须放在try的一对小括号中
    //        try(InputStreamReader reader = new InputStreamReader(System.in)){
    //            char[] cbuf = new char[20];
    //            int len;
    //            if((len = reader.read(cbuf) )!= -1){
    //                String str = new String(cbuf,0,len);
    //                System.out.println(str);
    //            }
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        }
    
            //java9中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外。
            //此时的资源属性是常量,声明为final的,不可修改
            InputStreamReader reader = new InputStreamReader(System.in);
            try (reader) {
                char[] cbuf = new char[20];
                int len;
                if((len = reader.read(cbuf) )!= -1){
                    String str = new String(cbuf,0,len);
                    System.out.println(str);
                }
    //            reader = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    java9新特性:String底层存储结构的变更

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

      public final class String
              implements java.io.Serializable, Comparable<String>, CharSequence {
          @Stableprivate 
          final byte[] value;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 那StringBuffer和StringBuilder呢?

      也改为byte[]数组

    java9新特性:集合工厂方法创建只读集合

    • 创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合
      • 构造,分配,添加元素之后, 就不能对该不可变集合进行CRUD操作,否则抛出异常 java.lang.UnsupportedOperationException
    import org.junit.Test;
    
    import java.util.*;
    
    public class Java9Test2 {
    
        //java9新特性八:集合工厂方法:创建只读集合
        //java8中的写法:
        @Test
        public void test() {
            List<String> namesList = new ArrayList<>();
            namesList.add("Joe");
            namesList.add("Bob");
            namesList.add("Bill");
            //返回的namesList是一个只读的集合
            namesList = Collections.unmodifiableList(namesList);
            namesList.add("Franck"); // 抛出异常
    
            System.out.println(namesList);
        }
    
        @Test
        public void  test2(){
            List<String> list = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
            Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
            // 如下操作不适用于jdk 8 及之前版本,适用于jdk 9
            Map<String, Integer> map = Collections.unmodifiableMap(new HashMap<>() {
                {
                    put("a", 1);
                    put("b", 2);
                    put("c", 3);
                }
            });
            map.forEach((k, v) -> System.out.println(k + ":" + v));
        }
    
        @Test
        public void test3() {
            //此时得到的集合list也是一个只读集合。
            List<Integer> list = Arrays.asList(1, 7, 9, 3, 2);
            //报异常
            list.add(6);
        }
    
        @Test
        public void test4() {
            List<Integer> list1 = List.of(1, 2, 3, 4, 5);
            //不能添加
    //        list1.add(6);
            System.out.println(list1);
    
            Set<Integer> set1 = Set.of(23, 3, 54, 65, 43, 76, 87, 34, 46);
            //不能添加
    //        set1.add(4);
            System.out.println(set1);
    
            Map<String, Integer> map1 = Map.of("Josh", 23, "Jack", 54, "Franck", 12);
            //不能添加
            //map1.put("George",34);
    
            System.out.println(map1);
    
            Map<String, Integer> map2 = Map.ofEntries(Map.entry("Josh", 34), Map.entry("Jim", 21));
    //        map2.put("George",34);
            System.out.println(map2);
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    java9新特性:InputStream中的transferTo()方法

    InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例。

    import org.junit.Test;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class Java9Test2 {
    
        //java9新特性九:InputStream的新方法:tranferTo()
        @Test
        public void test5() {
            ClassLoader cl = this.getClass().getClassLoader();
            try (InputStream is = cl.getResourceAsStream("hello.txt");
                 OutputStream os = new FileOutputStream("src\\hello1.txt")) {
                is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    java9新特性:StreamAPI新增的4个方法

    • 在Java 9 中,Stream API 变得更好,Stream 接口中添加了4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个Predicate (判断条件)来指定什么时候结束迭代
    • 除了对Stream 本身的扩展,Optional 和Stream 之间的结合也得到了改进。现在可以通过Optional 的新方法stream() 将一个Optional 对象转换为一个(可能是空的) Stream 对象。
    import org.junit.Test;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Stream;
    
    
    public class Java9Test3 {
    
        //java9新特性十:Stream API的加强
        @Test
        public void test(){
            List<Integer> list = Arrays.asList(23, 43, 45, 55, 61, 54, 32, 2, 45, 89, 7);
            //takeWhile 返回从开头开始的按照指定规则尽量多的元素
    //        list.stream().takeWhile(x -> x < 60).forEach(System.out::println);
    
    		// 移除指定条件的元素
            //dropWhile():与 takeWhile 相反,返回剩余的元素。
            list.stream().dropWhile(x -> x < 60).forEach(System.out::println);
        }
    
        @Test
        public void test2(){
            //of()参数中的多个元素,可以包含null值
            Stream<Integer> stream1 = Stream.of(1, 2, 3,null);
            stream1.forEach(System.out::println);
            
            //of()参数不能存储单个null值。否则,报空指针异常
    //        Stream stream2 = Stream.of(null);
    //        stream2.forEach(System.out::println);
    
            Integer i = 10;
            i = null;
            //ofNullable():形参变量是可以为null值的单个元素
            Stream<Integer> stream3 = Stream.ofNullable(i);
            long count = stream3.count();
            System.out.println(count); // 0
        }
    
        @Test
        public void test3(){
    		// 从0开始, 无限递增1, 限制limit为10
            Stream.iterate(0,x -> x + 1).limit(10).forEach(System.out::println);
    
            //java9中新增的重载的方法
    		// 从0开始, 每次递增1, 但递增的结果要<100
            Stream.iterate(0,x -> x < 100,x -> x + 1).forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    java9新特性:Optional的新方法stream()

     //java9新特性十一:Optional提供了新的方法stream()
    @Test
    public void test4(){
        List<String> list = new ArrayList<>();
        list.add("Tom");
        list.add("Jerry");
        list.add("Tim");
    
        Optional<List<String>> optional = Optional.ofNullable(list);
        Stream<List<String>> stream = optional.stream();
    //        long count = stream.count();
    //        System.out.println(count);
        stream.flatMap(x -> x.stream()).forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Java 10 的新特性

    java10新特性:局部变量类型推断

    • 产生背景

      开发者经常抱怨Java中引用代码的程度。局部变量的显示类型声明,常常被认为是不必须的,给一个好听的名字经常可以很清楚的表达出下面应该怎样继续。

    • 好处:减少了啰嗦和形式的代码,避免了信息冗余,而且对齐了变量名,更容易阅读!

    • 举例如下:

      • 场景一:类实例化时

        作为Java开发者,在声明一个变量时,我们总是习惯了敲打两次变量类型,第一次用于声明变量类型,第二次用于构造器。

        LinkedHashSet<Integer> set= new LinkedHashSet<>();
        
        • 1
      • 场景二:返回值类型含复杂泛型结构

        变量的声明类型书写复杂且较长,尤其是加上泛型的使用

        Iterator<Map.Entry<Integer, Student>> iterator= set.iterator();
        
        • 1
      • 场景三:我们也经常声明一种变量,它只会被使用一次,而且是用在下一行代码中,比如:

        URL url= new URL("https://www.waysto.work/");
        URLConnection connection= url.openConnection();
        Reader reader= newBufferedReader(new InputStreamReader(connection.getInputStream()));
        
        • 1
        • 2
        • 3
    import org.junit.Test;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    public class JDK10Test {
        /**
         * java10新特性一:局部变量的类型推断
         */
        @Test
        public void test(){
            //1.声明变量时,根据所附的值,推断变量的类型
            var num = 10;
    
            var list = new ArrayList<Integer>();
            list.add(123);
    
            //2.遍历操作
            for (var i : list) {
                System.out.println(i);
                System.out.println(i.getClass());
            }
    
            //3.普通的遍历操作
            for (var i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    
        @Test
        public void test2(){
            //1.局部变量不赋值,就不能实现类型推断
    //        var num ;
    
            //2.lambda表示式中,左边的函数式接口不能声明为var
    //        Supplier sup = () -> Math.random();
    
    //        var sup = () -> Math.random();
    
            //3.方法引用中,左边的函数式接口不能声明为var
    //        Consumer con = System.out::println;
    
    //        var con = System.out::println;
    
            //4.数组的静态初始化中,注意如下的情况也不可以
            int[] arr = {9, 5, 2, 7};
    //        var arr = {9,5,2,7};
        }
    
        @Test
        public void test3() {
    //        情况1:没有初始化的局部变量声明
    //        var s = null;
            
    //        情况6:catch块
    //        try{
    //
    //        }catch(var e){
    //            e.printStackTrace();
    //        }
        }
        //情况2:方法的返回类型
    //    public var method1(){
    //
            return 0;
    //    }
        // 情况3:方法的参数类型
    //    public void method2(var num){
    //
    //    }
    
        //情况4:构造器的参数类型
    //    public Java10Test(var i){
    //
    //    }
    
        //情况5:属性
    //    var num;
    
    
        @Test
        public void test4() {
            try {
                var url = new URL("http://www.waysto.work/");
                var connection = url.openConnection();
                var reader = new BufferedReader(
                        new InputStreamReader(connection.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 工作原理

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

    • 注意

    • var不是一个关键字

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

    • 这不是JavaScript

    • 首先我要说明的是,var并不会改变Java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。下面是使用IntelliJ(实际上是Fernflower的反编译器)反编译器反编译出的代码

    java10新特性:集合新增创建不可变集合的方法

    • 自Java9开始,Jdk里面为集合(List/Set/Map)都添加了of (jdk9新增)和copyOf(jdk10新增)方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class JDK10Test {
    
        //java10的新特性二:集合中新增的copyOf(),用于创建一个只读的集合
        @Test
        public void test5(){
            //示例1:
            // list1 本身就是不可变集合
            var list1 = List.of("Java", "Python", "C");
            // copyof后, copy1也是不可变集合
            var copy1 = List.copyOf(list1);
            System.out.println(list1 == copy1); // true
    
            //示例2:
            // list2是可变集合
            var list2 = new ArrayList<String>();
            list2.add("KKK");
            // copyof后, copy2变为不可变集合
            var copy2 = List.copyOf(list2);
            System.out.println(list2 == copy2); // false
    
            //示例1和2代码基本一致,为什么一个为true,一个为false?
            //结论:copyOf(Xxx coll):如果参数coll本身就是一个只读集合,则copyOf()返回值即为当前的coll
            //如果参数coll不是一个只读集合,则copyOf()返回一个新的集合,这个集合是只读的。
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 从 源 码 分 析,可以看出copyOf方 法 会 先 判 断 来 源 集 合 是 不 是AbstractImmutableList类型的,如果是,就直接返回,如果不是,则调用of创建一个新的集合。
    • 示例2因为用的new创建的集合,不属于不可变AbstractImmutableList类的子类,所以copyOf方法又创建了一个新的实例,所以为false。
    • 注意:使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报java.lang.UnsupportedOperationException异常。
    • 上面演示了List的of和copyOf方法,Set和Map接口都有。

    Java 11 的新特性

    java11新特性:String新增的方法

    描述举例
    判断字符串是否为空白" ".isBlank(); // true
    去除首尾空白" Javastack ".strip(); // “Javastack”
    去除尾部空格" Javastack “.stripTrailing(); // " Javastack”
    去除首部空格" Javastack ".stripLeading(); // "Javastack "
    复制字符串“Java”.repeat(3);// “JavaJavaJava”
    行数统计“A\nB\nC”.lines().count(); // 3
    import org.junit.Test;
    
    public class JDK11Test {
        
        //java 11新特性一:String中新增的方法
        @Test
        public void test(){
    //        isBlank():判断字符串是否为空白
            System.out.println("  \t  \t  \n  ".isBlank());
    //        strip():去除首尾空白
            System.out.println("++++" + "  \t abc \t  \n  ".strip() + "++++");
            System.out.println("++++" + "  \t abc \t  \n  ".trim() + "++++");
    //        stripTrailing():去除尾部空格
            System.out.println("++++" + "  \t abc \t  \n  ".stripTrailing() + "++++");
    //        stripLeading():去除首部空格
            System.out.println("++++" + "  \t abc \t  \n  ".stripLeading() + "++++");
    //        repeat(int count):复制字符串
            String str1 = "abc";
            String str2 = str1.repeat(5);
            System.out.println(str2);
    
    //        lines().count():行数统计
            String str3 = "abc\nEFG\nH";
            System.out.println(str3.lines().count());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    java11新特性:Optional新增的方法

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

    新增方法描述新增的版本
    boolean isEmpty()判断value是否为空JDK 11
    ifPresentOrElse(Consumeraction,RunnableemptyAction)value非空,执行参数1功能;如果value为空,执行参数2功能JDK 9
    Optionalor(Supplier>supplier)value非空,返回对应的Optional;value为空,返回形参封装的OptionalJDK 9
    Streamstream()value非空,返回仅包含此value的Stream;否则,返回一个空的StreamJDK 9
    TorElseThrow()value非空,返回value;否则抛异常NoSuchElementExceptionJDK 10
    import org.junit.Test;
    
    import java.util.Optional;
    
    
    public class JDK11Test {
    
        //java11新特性二:Optional新增的方法
        @Test
        public void test2(){
            var op = Optional.empty();
            System.out.println(op.isPresent());//判断内部的value是否存在
            System.out.println(op.isEmpty());//判断内部的value是否为空
    
            op = Optional.of("abc");
            //orElseThrow():value非空,返回value;否则抛异常NoSuchElementException
            var obj = op.orElseThrow();
            System.out.println(obj);
    
            Optional<String> op1 = Optional.of("hello");
    //        op = Optional.empty();
            //or:value非空,返回对应的Optional;value为空,返回形参封装的Optional
            Optional<Object> op2 = op.or(() -> op1);
            System.out.println(op2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

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

    import org.junit.Test;
    
    import java.util.function.Consumer;
    
    public class JDK11Test {
    
        //java11新特性三:局部变量类型推断的升级
        @Test
        public void test3(){
            //错误的形式: 必须要有类型, 可以加上var
    //        Consumer con1 = (@Deprecated t) -> System.out.println(t.toUpperCase());
            // 正确的形式:
            // 使用var的好处是在使用lambda表达式时给参数加上注解。
            Consumer<String> con2 = (@Deprecated var t) -> System.out.println(t.toUpperCase());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    java11新特性:HttpClient

    • HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年,HTTP2才成为标准。

    在这里插入图片描述

    • HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。HTTP/2允许服务器“push”数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据。
    • 这是Java9开始引入的一个处理HTTP请求的的HTTPClientAPI,该API支持同步和异步,而在Java11中已经为正式可用状态,你可以在java.net包中找到这个API。
    • 它将替代仅适用于blocking模式的HttpURLConnection(HttpURLConnection是在HTTP1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket和HTTP/2的支持。
    • day13——module-info.java类
    module day13 {
        requires JDK9Test;  //requires 包名---》接收包
        requires junit;//若要调用JDK9以上版本的测试类,需要引入
        exports github;
        exports github2;
        exports github3;
        requires java.net.http;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 测试类
    import org.junit.Test;
    
    import java.io.IOException;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.util.concurrent.CompletableFuture;
    
    public class JDK11Test {
    
        //java11新特性四:HttpClient替换原有的HttpURLConnection。
        @Test
        public void test4(){
            try {
                HttpClient client = HttpClient.newHttpClient();
                HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
                HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
                HttpResponse<String> response = client.send(request, responseBodyHandler);
                String body = response.body();
                System.out.println(body);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        @Test
        public void test5(){
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
            HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
            CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, responseBodyHandler);
            sendAsync.thenApply(t -> t.body()).thenAccept(System.out::println);
            //HttpResponse response = sendAsync.get();
            //String body = response.body();
            //System.out.println(body);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    java11新特性:简化编译运行程序 Java命令

    看下面的代码。
        //编译
        javac Javastack.java
        //运行
        java Javastack
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在我们的认知里面,要运行一个Java源代码必须先编译,再运行,两步执行动作。而在未来的Java11版本中,通过一个java命令就直接搞定了,如以下所示:

    java test.java文件即可, 包含了之前的javac, java命令

    一个命令编译运行源代码的注意点:

    • 执行源文件中的第一个类, 第一个类必须包含主方法。
    • 并且不可以使用其它源文件中的自定义类, 本文件中的自定义类是可以使用的。

    Java语言高级-java11新特性:其它新特性

    ZGC (垃圾回收器)

    • GC是java主要优势之一。然而,当GC停顿太长,就会开始影响应用的响应时间。消除或者减少GC停顿时长,java将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存,并且无需长时间的GC暂停时间。
    • ZGC,AScalableLow-LatencyGarbageCollector(Experimental) ZGC,这应该是JDK11最为瞩目的特性,没有之一。但是后面带了Experimental,说明这还不建议用到生产环境。
    • ZGC是一个并发,基于region,压缩型的垃圾收集器,只有root扫描阶段会STW(stoptheworld),因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。
    • 优势:
      • GC暂停时间不会超过10ms
      • 既能处理几百兆的小堆,也能处理几个T的大堆(OMG)
      • 和G1相比,应用吞吐能力不会下降超过15%
      • 为未来的GC功能和利用colord指针以及Loadbarriers优化奠定基础
      • 初始只支持64位系统
    • ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。

    其他的新特性

    • Unicode 10
    • Deprecate the Pack200 Tools and API
    • 新的Epsilon垃圾收集器
    • 完全支持Linux容器(包括Docker)
    • 支持G1上的并行完全垃圾收集
    • 最新的HTTPS安全协议TLS 1.3
    • Java Flight Recorder

    在当前JDK中看不到什么?新的货币API

    新的货币API

    • 对许多应用而言货币价值都是一个关键的特性,但JDK对此却几乎没有任何支持。严格来讲,现有的java.util.Currency类只是代表了当前ISO4217货币的一个数据结构,但并没有关联的值或者自定义货币。JDK对货币的运算及转换也没有内建的支持,更别说有一个能够代表货币值的标准类型了。
    • 此前,Oracle公布的JSR354定义了一套新的Java货币API:JavaMoney,计划会在Java9中正式引入。但是目前没有出现在JDK新特性中。
    • 不过,如果你用的是Maven的话,可以做如下的添加,即可使用相关的API处理货币:
    <dependency>
        <groupId>org.javamoney</groupId>
        <artifactId>moneta</artifactId>
        <version>0.9</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    关于JDK版本

    由于现在企业主流还是使用JDK8, 后续因为JDK11是长期版本, 所以完全有必要去学习。JDK12,13,14都是小版本, 想了解的可以学习下, 目前已经出的JDK17也是长期版本, 需要的人可以自学下。

  • 相关阅读:
    React-native Android 添加音效
    Gem5 Fullsystem,Spec2017
    Building a Robust Data Infrastructure for Cloud Computing Platforms
    【PythonIQ测试系统】学了一招测试一下女友的智商,这离谱的反射弧~麻了麻了(终极智商测试)
    Java | 类、实例初始化 、方法重写规则
    路径几何图形的各种线段
    香橙派配合IIC驱动OLED & 使用SourceInsight解读源码
    一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
    图书管理系统的设计与实现/ssm的图书管理网站
    机器学习(二十一):类不平衡处理之权重法
  • 原文地址:https://blog.csdn.net/m0_37989980/article/details/126109312