java 8-17 新特性(学习留存,欢迎交流)

目录

一、java 8 新特性

二、java 9 新特性

三、java 10 新特性

四、Java 11 新特性

五、Java 12-16 新特性

六、java 17 新特性


一、java 8 新特性

  1. Lambda表达式

    1. 匿名内部类: 使用条件:当需要实现的接口有且仅有一个抽象方法时,我们就可以将实现接口的代码替换为 (方法的参数名)->方法的实现逻辑

      如:实现Runnable的匿名内部类:

      本来我们要想实现一个Runnable匿名内部类并且创建一个线程,我们需要完整的实现run方法再创建线程:

      public class Main {
          public static void main(String[] args) {
              Thread thread = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("不使用lambda表达式");
                  }
              });
              thread.start();
          }
      }

      由于只需要实现一个方法,因此可以使用lambda表达式,run方法没有参数因此lambda表达式也不需要参数,可以写为下面的代码大幅缩减代码的编写量

      public class Main {
          public static void main(String[] args) {
              Thread thread = new Thread(() -> {System.out.println("使用lambda表达式")});
              thread.start();
          }
      }

      并且匿名内部类会单独编译成一个class文件,而lambda表达式不会。但是lambda表达式只支持接口,不能支持抽象类。

      当参数只有一个时,也可以省略()只留参数名字,并且实现语句只有一句时也可以省略{}。

      举个例子,我们创建一个接口

      public interface Interface {
          void method(int i);
      }

      实现它,直接省略()和{},当然,只有参数有且仅有一个时才可以省略(),实现语句有且仅有一条时才能省略{}

      public class Main {
          public static void main(String[] args) {
              Interface inter = i -> System.out.println(i);
              inter.method(1);
          }
      }

      总结:lambda表达式仅能用于接口不能用于抽象类,并且接口中必须有有且仅有一个方法需要实现才可以使用。在使用时,使用的形式如([参数名1,参数名2.....]) -> {实现语句},当参数有且仅有一个时可以省略(),当实现语句有且仅有一个时可以省略{}

  2. 基于lambda表达式的函数式接口(@FunctionalInterface)

    1. Supplier供给型函数时接口 仅有一个需要实现的get()方法用于获取需要的对象,返回值是泛型类,如下:当需要一个新的学生对象时调用get方法即可

      public class Main {
      ​
          public static void main(String[] args) {
              Supplier<Student> studentSupplier = () -> new Student();
              studentSupplier.get().supplier();
          }
      ​
          public static class Student {
              public void supplier(){
                  System.out.println("学生类供给式函数式接口");
              }
          }
      }
    2. Consumer消费型函数式接口 仅有一个需要实现的accept(T)方法用于获取需要的对象,返回值是void型,传入的参数用于消费

      public class Main {
      ​
          public static void main(String[] args) {
              Consumer<Student> studentConsumer = student -> System.out.println(student+"已被消费");
              studentConsumer.accept(new Student());
          }
      ​
          public static class Student {
          }
      }

      还有一个默认实现了的andThen(Consumer)方法,如果这个方法传入的Consumer参数是空就会抛异常,如果不为空就会在执行完accept后执行,同一个消费型函数时接口对象只能同时调用一次accept方法,但是可以多次调用andThen方法,他们会顺序执行,且该方法只会在accept方法执行完成后执行,单独调用不会执行

      public class Main {
      ​
          public static void main(String[] args) {
              Consumer<Student> studentConsumer = student -> System.out.println(student+"已被消费");
              studentConsumer
                      .andThen(student -> System.out.println("消费完成1!"))
                      .andThen(student -> System.out.println("消费完成2!"))
      //                .accept(new Student()) 连续调用报错
                      .accept(new Student());
          }
      ​
          public static class Student {
          }
      }
    3. Function函数型函数式接口 仅有一个需要实现的apply(T)方法,返回值是泛型类R

      public class Main {
      ​
          public static void main(String[] args) {
          //举例:接收的T类型为Integer类型,返回的R类型为String类型
              Function<Integer,String> studentFunction = (num) -> String.valueOf(num);
              System.out.println(studentFunction.apply(1));
          }
      }

      默认实现的compose(Function)方法,此方法在调用时会先将传入apply的参数进行操作然后再执行apply方法,andThen(Function)方法会在最后在对apply方法处理后的返回值进行处理

      public static void main(String[] args) {
              Function<Integer,String> studentFunction = (num) -> String.valueOf(num);
              //compose方法先将传入的参数转化为Integer类型,然后将Integer类型通过apply方法转化为String类型,最后通过andThen方法将String类型转化为Integer类型
              //即 String -> Integer -> String -> Integer
              System.out.println(
                      studentFunction
                              .andThen((String i)-> i.length())
                              .compose((String str)->str.length())
                              .apply("lbw nb")
              );
              //"lbw nb" -> 6 -> "6" -> 1
          }

      identity将传入的参数原样返回,个人认为没什么用,感兴趣的可以自己看一下

    4. Predicate断言型函数式接口 仅有一个需要实现的方法test(T),返回值为boolean

      public static void main(String[] args) {
              Predicate<Integer> stringPredicate = (num) -> num >= 17;
              Integer num = 17;
              if(stringPredicate.test(num)){
                  System.out.println("十七张牌你能秒我,我直接把这个电脑吃掉");
              }else {
                  System.out.println("全体起立");
              }
          }

      and(Predicate)方法,和test同时满足时才为true

      public static void main(String[] args) {
              Predicate<Integer> integerPredicate = (grade) -> grade >= 60;
              //and方法,如果和test同时满足
              if(integerPredicate
                      .and((Integer grade) -> grade >= 90)
                      .test(70)){
                  System.out.println("90分,高手");
              }
          }

      or(Predicate)放啊,和test有一个满足为true

      public static void main(String[] args) {
              Predicate<Integer> integerPredicate = (num) -> num == 0;
              //or(Predicate)方法,和grade有一个满足即可
              if(integerPredicate
                      .or((Integer i) -> i > 0)
                      .test(17)){
                  System.out.println("让我猜一猜,这个数是一个非负数");
              }
          }

      negate,将test方法结果取反

      public static void main(String[] args) {
              Predicate<Integer> integerPredicate = (num) -> num == 0;
              //negate方法,会将test方法的结果取反
              System.out.println(integerPredicate
                      .negate().test(0));
          }
  3. 判空包装类Optional类:处理空指针异常

    of(T)方法传入一个参数包装,如果参数为null会报异常,ofNullable(T)如果传入参数为null,不会报异常

    ifPresent(Consumer)方法,如果包装的不为null,实现消费型函数式接口来消费传入的参数

    public static void main(String[] args) {
            method("字符串");
            method(null);
        }
    
        public static void method(String str) {
            Optional
                    .ofNullable(str)
                    .ifPresent(s-> System.out.println(s));
        }

    get()方法获取包装的对象,如果包装的是空,get方法会报异常

    public static void main(String[] args) {
            System.out.println(method("字符串"));
            System.out.println(method(null));
        }
    
        public static String method(String str) {
            return Optional
                    .ofNullable(str)
                    .get();
        }

    orElse(T)方法,如果包装的是空,就传入参数T并返回T

    public static void main(String[] args) {
            System.out.println(method("字符串"));
            System.out.println(method(null));
        }
    
        public static String method(String str) {
            return Optional
                    .ofNullable(str)
                    .orElse("重新包装");
        }

    orElseGet(Supplier),如果包装的是空,就传入supplier然后经过操作后再返回一个值

    public static void main(String[] args) {
            System.out.println(method("字符串"));
            System.out.println(method(null));
        }
    
        public static String method(String str) {
            return Optional
                    .ofNullable(str)
                    .orElseGet(()-> "重新包装");
        }

    orElseThrow(Exception)如果包装的是空,会抛出传入的异常

    还有一些其他的方法,感兴趣的可以自己学习

还有一些其他的不常用改进,感兴趣的可以再自行查阅

二、java 9 新特性

  1. 模块机制

  2. JShell交互式编程 在命令行窗口中输入jshell,就可以在命令行窗口中进行java代码编写,vars用于看变量的定义,methods用于看方法的定义,感兴趣的话其他的命令可以自行学习

  3. 接口中的私有方法 我们知道,java8中的接口只能有常量、抽象方法、静态方法和default方法,如果我们在接口中的default方法和静态方法中需要频繁的使用一些代码,但这些代码我们又不想让子类看到,怎么办呢?在java9中给接口增加了私有方法,让我们可以实现代码的复用同时又不让子类看到,私有方法在接口中必须实现。

  4. 集合类新增工厂方法 在java9之前,我们要想给集合类里面提前加一些数据,必须要先进行集合类的定义和初始化,然后才能一个个添加如:

    public class Main {
        public static void main(String[] args) {
            HashMap<Integer,String> hashMap = new HashMap();
            hashMap.put(1,"1");
            hashMap.put(2,"2");
        }
    }

    现在增加了工厂方法,可以直接通过of方法来提前添加,但是注意提前添加的元素无法进行修改,对其他的集合也是这样

    public class Main {
        public static void main(String[] args) {
            Map<Integer,String> map = Map.of(1,"1",2,"2",3,"3");
        }
    }
  5. 改进 stream API

    1. of改进

      将集合进行过滤和去重后收集,此时of中传入null会报错

    public class Main {
        public static void main(String[] args) {
            List<Integer> list = Stream.of(1,2,3,4)
                    .filter(t->t.equals("3"))
                    .distinct()
                    .collect(Collectors.toList());
        }
    }

    改进后使用ofNullable可以允许传入null,但是每次只能一个传入一个

    public class Main {
        public static void main(String[] args) {
           Stream
                    .ofNullable(null)
                    .forEach(System.out::println);
        }
    }
    1. iterate limit改进更加类似于for循环 往流中不断的加入一些元素

      public class Main {
          public static void main(String[] args) {
              Stream
                      .iterate(0,i->i+1)
                      .limit(20)
                      .forEach(System.out::println);
          }
      }

      改进后可以直接限制次数

      public class Main {
          public static void main(String[] args) {
              Stream
                      .iterate(0,i -> i < 20,i -> i+1)
                      .forEach(System.out::println);
          }
      }
    2. 新增对数据的截断操作

      takewhile 当满足条件时在进行操作

      public class Main {
          public static void main(String[] args) {
              Stream
                      .iterate(0, i -> i < 20, i -> i + 1)
                      .takeWhile(i -> i < 10)
                      .forEach(System.out::println);
          }
      }

      dropwhile 当满足条件时不操作

      public class Main {
          public static void main(String[] args) {
              Stream
                      .iterate(0, i -> i < 20, i -> i+1)
                      .dropWhile(i -> i < 10)
                      .forEach(System.out::println);
          }
      }
  6. try-with-resource

    在java9之前,我们要将需要关闭的资源的定义和初始化全部放入try()中才可以,java9中我们可以先定义和初始化,再将需要关闭的资源的变量名放入到try()中去。

  7. optional类的改进

    1. ifPresentOrElse(Consumer,Runnable)可以同时处理为空和不为空的两个情况了,如果不为空执行Consumer,否则执行runnable

      public static void main(String[] args) {
              method("字符串");
              method(null);
          }
      
          public static void method(String str) {
              Optional
                  .ofNullable(str)
                  .ifPresentOrElse(s-> System.out.println(s),()-> System.out.println("传入参数为空"));
          }
    2. or(Supplier)如果为空,就用一个option替换掉这个optional

      public static void main(String[] args) {
              method("字符串");
              method(null);
          }
      
          public static void method(String str) {
              Optional
                  .ofNullable(str)
                  .or(()->Optional.ofNullable("替换的包装"))
                      .ifPresent(s-> System.out.println(s));
          }
  8. 泛型的改进

    我们定义了如下抽象类

    public abstract class Test<T> {
        private T t;
        public Test(T t){
            this.t = t;
        }
        public void method(){
            System.out.println(t);
        }
    }

    在java9之前的版本中,无法自动识别传入的参数的类型并报错,但是java9中java会自动推断类型不会报错

    public class Main {
        public static void main(String[] args) {
            Test<String> test = new Test<>("aaa") {};
            test.method();
        }
    }

还有一些其他的不常用改进,感兴趣的可以再自行查阅

三、java 10 新特性

  1. 局部变量类型推断

    var类型推断,使用var在定义变量时替代变量类型,只能用于在定义时初始化的变量且仅适用于局部变量

    public class Main {
        public static void main(String[] args) {
            var a = "aaa";
            System.out.println(a.toUpperCase());
        }
    }

还有一些其他的不常用改进,感兴趣的可以再自行查阅

四、Java 11 新特性

  1. 用于Lambda的形参局部变量语法

    public class Main {
        public static void main(String[] args) {
            Consumer<String> consumer = (var str) -> {
                System.out.println(str);
            };
            consumer.accept("形参");
        }
    }
  2. 针对String 的方法改进

    1. 判断字符串中是否全部为空格 isBlank()方法

    2. 将字符串重复拼接n次并返回 repeat(n)方法

    3. 根据换行符判断字符串分为几部分 .lines().count() .lines()方法会将字符串根据换行符分段为流,conut()可以计数

    4. 去除首尾空格,strip() 是trim()的增强版,trim()无法去除unicode空白字符,而strip可以

五、Java 12-16 新特性

  1. 新switch语法(14正式开放) switch可以有返回值并且写法更简洁,但这种写法必须要包含所有返回值,否则报错,因此要写default

    public class Main {
        public static void main(String[] args) {
            System.out.println(grade(77));
        }
    
        public static String grade(int score){
            score /= 10;
            return switch (score){
                case 10,9 -> "优秀";
                case 8,7 -> "良好";
                case 6 -> "及格";
                default -> "不及格";
            };
        }
    }

    如果我们最后在case中还要进行一些操作再进行返回,要使用yield关键字

    public class Main {
        public static void main(String[] args) {
            System.out.println(grade(95));
        }
    
        public static String grade(int score){
            score /= 10;
            return switch (score){
                case 10,9 -> {
                    System.out.println("点名表扬");
                    yield "优秀";
                }
                case 8,7 -> "良好";
                case 6 -> "及格";
                default -> {
                    System.out.println("打电话叫家长");
                    yield "不及格";
                }
            };
        }
    }
  2. 三引号(15正式开放) 字符串在编写时不需要对特殊字符进行转义,而是全部认为是字符,但是不能连续出现三个"

    public class Main {
        public static void main(String[] args) {
            String str = "111";
            String a = """
                    dasd <a href = str.length '' '
                    """;
            System.out.println(a);
        }
    }
  3. 空指针改进:可以更明确的指出空指针的异常原因。比如再类型转换时如果为空,会明确告诉你由于传入的参数为空因此无法类型转换,而在改进之前只会告诉你空指针异常,原因需要你自己找寻。

  4. 记录类型(Record),参数会自动实现set、get、hashcode等方法(java16开放)

    写一个学生类

    public record Student(String id, String name,int age) {
    }
    调用自动实现的方法
    
    public class Main {
        public static void main(String[] args) {
            Student student = new Student("123","张三",19);
            System.out.println(student.age());
            System.out.println(student.toString());
            System.out.println(student);
        }
    }

六、java 17 新特性

  1. 密封类型 sealed 关键字修饰类,仅让被允许的子类继承

    我们让A被修饰,让B去继承A

    public sealed class A permits B {
    }
    public final class B extends A {
    }
    1. 密封类型可以基于普通类、抽象类、接口,也可以是继承自其他抽象类的子类或者是实现其他接口的类等。

    2. 必须有子类,且不能是匿名内部类

    3. sealed不能与final、non-sealed同时出现

    4. 继承的子类必须为final、sealed或是non-sealed的

学习参考: 青空の霞光的个人空间-青空の霞光个人主页-哔哩哔哩视频

                   青空の霞光-CSDN博客

java新手,欢迎大家学习、交流和批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aayasu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值