JAVA8

whats new in Java8: https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html   1. lambda表达式
  • http://www.importnew.com/26080.html
  • Java8 lambda表达式10个示例 http://www.importnew.com/16436.html
  • 为什么要用lambda
    • 又称闭包或匿名函数,用来代替匿名内部类
    • 使代码变的更加紧凑
    • new Thread(() -> System.out.println("Hello World!")).start();
  • 修改方法的能力:函数中可以接受以函数为单元的参数
    • String []datas = new String[] {"peng","zhao","li"};
    • Arrays.sort(datas,(v1 , v2) -> Integer.compare(v1.length(), v2.length()));
  • 语法
    • 单行表达式
    • (params) -> an expression
    • 多个语句块
    • (params) -> {expressions;};
    • 没有参数,用空括号表示
    • () -> {for (int i = 0; i < 1000; i++) doSomething();};`
    • Java是一个强类型的语言,因此参数必须要有类型,如果编译器能够推测出Lambda表达式的参数类型,则不需要我们显示的进行指定
      • Arrays.sort(datas,(v1, v2) -> Integer.compare(v1.length(), v2.length()));
      • 编译器会根据Lambda表达式对应的函数式接口Comparator进行自动推断
    • 如果Lambda表达式只有一个参数,并且参数的类型是可以由编译器推断出来的
      • Stream.of(datas).forEach(param -> {System.out.println(param.length());});`
      • Lambda表达式的返回类型,无需指定,编译器会自行推断,说是自行推断
      • 参数可以使用修饰符及注解,如final、@NonNull等
  • 方法引用
    • String []datas = new String[] {"peng","Zhao","li"};
    • Arrays.sort(datas,String::compareToIgnoreCase);
    • Stream.of(datas).forEach(System.out::println);
    • 方法引用的具体分类
      • Object:instanceMethod
      • Class:staticMethod
      • Class:instanceMethod
    • 两种在Lambda表达式的意义上等同
      • System.out::println == x -> System.out.println(x);
      • String::compareToIgnoreCase == (x,y) -> x.compareToIgnoreCase(y)
  • java 8中内部类或者Lambda表达式对外部类变量的引用,不要求强制的加上final关键字了,但是Java 8中要求这个变量是effectively final(有效只读变量,一旦定义后,在后面就不能再随意修改)
``` String []datas = new String[] {"peng","Zhao","li"}; datas = null; new Thread(() -> System.out.println(datas)).start(); //compile error ```
  • Java中内部类以及Lambda表达式中也不允许修改外部类中的变量,这是为了避免多线程情况下的race condition
  • 缺点
    • variable used in lambda expression should be final or effectively final
    • lambda和inner class中的变量都得是final
    • 如果在匿名类或 Lambda 表达式中访问的局部变量,如果不是 final 类型的话,编译器自动加上 final 修饰符
``` String version = "1.8"; version = "1.7"; //注释掉这行或下行中另一行才能编译通过 foo(() -> version ); //这行让编译器决定给 version 加上 final 属性 ```
  • 解释:为什么 Lambda 表达式(匿名类) 不能访问非 final 的局部变量呢?因为实例变量存在堆中,而局部变量是在栈上分配,Lambda 表达(匿名类)会在另一个线程中执行。如果在线程中要直接访问一个局部变量,可能线程执行时该局部变量已经被销毁了,而 final 类型的局部变量在 Lambda 表达式(匿名类) 中其实是局部变量的一个拷贝。
    2. 接口的默认方法
  • 在Java8种引入新的机制,支持在接口中声明方法同时提供实现
  • 这令人激动不已,你有两种方式完成
    • 1.在接口内声明静态方法
    • 2.指定一个默认方法
      • 比如List接口中添加了sort方法
      • Java8操作集合的时候可以直接foreach的原因也是在Iterable接口中也新增了一个默认方法:forEach
  3. 流API
  • 集合接口有两个方法来生成流:
    4. 方法引用
  • 方法引用使用一对冒号 ::
  • names.forEach(System.out::println);
  • Arrays.sort(arr, Comparator.comparing(SupplierHS::getCorpId).thenComparing(SupplierHS::getCorpName));
    5.FunctionalInterface
  • 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
  • java8中用lambda表达式代替匿名内部类,本质上是将接口定义为函数式接口,并将函数式接口隐式转换为lambda表达式
  • Predicate接口适合用于过滤,测试对象是否符合某个条件,唯一抽象方法是 boolean test(T t) 
  6. LocalDate、LocalTime、LocalDateTime
  • 为什么需要LocalDate、LocalTime、LocalDateTime
    • Date如果不格式化,打印出的日期可读性差
    • Date对时间处理比较麻烦,比如想获取某年、某月、某星期,以及n天以后的时间
    • 使用SimpleDateFormat对时间进行格式化,但SimpleDateFormat是线程不安全的
    • 解决SimpleDateFormat非线程安全问题?
      • 方法一:用DateTimeFormatter和FastDateFormat替换
      • 方法二:每次都创建新的SimpleDateFormat对象
      • 方法三:使用ThreadLocal保证每个线程最多只创建一次
  • LocalDate,只会获取年月日
    • LocalDate.now()
    • LocalDate.of(2019, 9, 10)
    • int year = localDate.getYear();
  • LocalTime,只会获取几点几分几秒
    • LocalTime.of(13, 51, 10)
  • LocalDateTime=LocalDate+LocalTime
    • 转instant:localDateTime.toInstant(ZoneOffset.of("+8"))
  • Instant,获取秒数、毫秒数
    • 可用来与Date对象转换
      • new Date(instant.toEpochMilli())
      • Date.from(instant)
  • 格式化
LocalDate localDate = LocalDate.of(2019, 9, 10);   String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);   String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);   //自定义格式化   DateTimeFormatter dateTimeFormatter =   DateTimeFormatter.ofPattern("dd/MM/yyyy");   String s3 = localDate.format(dateTimeFormatter);       8. Optional 类
  • 目的:减少空指针异常
  • https://www.cnblogs.com/zhangboyu/p/7580262.html
  • Optional.ofNullable(user),user可能为null
  • Optional.of(user),user不允许为null,否则报空指针
  • optional.get(),如果value为null,则报错:NoSuchElementException
  • optional.isPresent(),return value != null
  • optional.ifPresent(consumer)
  • optional.orElse(other),有值返回,无值返回other
  • optional.orElseGet(supplier)。
    • 与orElse的区别,有值的时候不会执行supplier
  • optional.orElseThrow(Supplier exceptionSupplier) throws X
  • optional.map((a) -> a.getName())
  • optional.flatmap((a) -> a.getName())
    • Funcation参数的返回值为Optional,flatmap返回解除包装的 String 值
  • optional.filter(predicate)
  • 链式
String result = Optional.ofNullable(user)   .flatMap(User::getAddress)   .flatMap(Address::getCountry)   .map(Country::getIsocode)   .orElse("default");  
  • 用例
List<User> users = new ArrayList<>(); User user = users.stream().findFirst().orElse(new User("default", "1234"));
  • Optional 不是 Serializable。因此,它不应该用作类的字段
     
上一篇:java8新特性


下一篇:java8 Function 函数式接口的妙用