【JavaSE】jdk8新特性

2023-11-12

尚硅谷JavaSE笔记合集

文章名 链接
【JavaSE】异常 文章地址
【JavaSE】常用类:String、LocalDateTime… 文章地址
【JavaSE】枚举 文章地址
【JavaSE】注解 文章地址
【JavaSE】集合框架 文章地址 | HashMap源码解析 | List相关实现类源码解析
【JavaSE】泛型 文章地址
【JavaSE】IO流 文章地址 | 字符编码详解
【JavaSE】网络编程,BIO需求演进 文章地址
【JavaSE】反射 文章地址
【JavaSE】jdk8新特性 文章地址

一、Java8概述

  • Java 8 (又称为jdk 1.8) 是Java 语言开发的一个主要版本。
  • Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。

在这里插入图片描述

二、Java8新特性的好处

  • 速度更快
  • 代码更少(增加了新的语法:Lambda 表达式)
  • 强大的Stream API
  • 便于并行
  • 最大化减少空指针异常:Optional
  • Nashorn引擎,允许在JVM上运行JS应用

三、并行流与串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。

Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过parallel() 与sequential() 在并行流与顺序流之间进行切换。

四、Lambda表达式

4.1 介绍

Lambda 是一个匿名函数,我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

总结:作为函数式接口的匿名实现类的实现

  • lambda形参列表:
    • 参数类型可以省略(类型推断)
    • 只有一个参数,()也可以省略
  • lambda体:应该使用一对{}包裹
    • 只有一条执行语句,省略{}
    • 只有return语句,省略return关键字

4.2 语法

//语法格式一:无参,无返回值
Runnable r2 = () -> System.out.println("长安欢迎您");


//语法格式二:一个参数,没有返回值。
Consumer<String> c1 = (String s) -> {
     System.out.println(s);
};
c1.accept("先天人性无善恶,后天人性有善恶。");


//语法格式三:因为可由编译器推断得出(“类型推断”),数据类型可以省略,
Consumer<String> c2 = (s) -> {
     System.out.println(s);
};
c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?");


//语法格式四:只需要一个参数时,小括号可以省略
Consumer<String> c2 = s -> {
     System.out.println(s);
};
c2.accept("如果没有邪恶的话我们怎么会知道人世间的那些善良呢?");


//语法格式五:需要两个或以上的参数,多条执行语句,并且可以有返回值
Comparator<Integer> com2 = (o1,o2) -> {
     System.out.println(o1);
     System.out.println(o2);
     return o1.compareTo(o2);
};
System.out.println(com2.compare(16,8));


//语法格式六:Lambda体只有一条语句时,return与大括号都可以省略
Comparator<Integer> c2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(c2.compare(17,24));

五、函数式接口

5.1、介绍

/*
 * 4.Lambda表达式的本质:作为函数式接口的实例
 */

/**
 * 自定义函数式接口
 */
@FunctionalInterface	//可以使用 @FunctionalInterface 检查它是否是一个函数式接口
public interface MyInterFace {
    void method();		//接口中,只声明了一个抽象方法  
}
  • java.util.function包下定义了Java 8 的丰富的函数式接口
  • Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持OOP还可以支持OOF(面向函数编程)
  • 在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口。
  • 简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示
  • 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。

5.2、内置函数式接口

函数式接口 参数类型 返回类型 用途
Consumer 消费型接口 T void 对类型为T的对象应用操作,包含方法:void accept(T t)
Supplier 供给型接口 T 返回类型为T的对象,包含方法:T get()
Function<T, R> 函数型接口 T R 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t)
Predicate断定型接口 T boolean 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法:boolean test(T t)
BiFunction<T,U,R> T, U R 对类型为T,U参数应用操作,返回R类型的结果。包含方法为:Rapply(T t,U u);
UnaryOperator(Function子接口) T T 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为:Tapply(T t);
BinaryOperator(BiFunction子接口) T,T T 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为:Tapply(T t1,T t2);
BiConsumer<T,U> T,U void 对类型为T,U参数应用操作。包含方法为:voidaccept(Tt,Uu)
BiPredicate<T,U> T,U boolean 包含方法为:booleantest(Tt,Uu)
ToIntFunction T int 计算int值的函数
ToLongFunction T long 计算long值的函数
ToDoubleFunction T double 计算double值的函数
IntFunction int R 参数为int类型的函数
LongFunction long R 参数为long类型的函数
DoubleFunction double R 参数为double类型的函数
/**
 * java内置的4大核心函数式接口
 *
 * 消费型接口 Consumer<T>     void accept(T t) 	有参数无返回值
 * 供给型接口 Supplier<T>     T get()		  	无参数有返回值
 * 函数型接口 Function<T,R>   R apply(T t)	  	有参数有返回值
 * 断定型接口 Predicate<T>    boolean test(T t)	有参数返回真假
 */

六、方法、构造器、数组引用

6.1 介绍

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

  • 格式:类(或对象) :: 方法名
  • 主要情况:
    • 对象 :: 非静态方法 【函数式接口中定义方法的形参列表和返回值类型与方法引用相同时可使用】
    • 类 :: 静态方法 【函数式接口中定义方法的形参列表和返回值类型与方法引用相同时可使用】
    • 类 :: 非静态方法 【函数式接口中定义方法的第一个参数作为方法引用中的类,其他参数作为形参列表或返回值类型】

6.2 方法引用

  • 对象::实例方法

        @Test
        public void demo1(){
            String str="abc";
            /*Consumer<String> consumer=(s)->{
                System.out.println(s);
            };*/
            Consumer<String> consumer=System.out::println;
            Supplier<Integer> supplier=str::length;
            Function<Integer,String> function=str::substring;
            Predicate<String> predicate=str::endsWith;
    
            consumer.accept("方法引用之实例::实例方法(Consumer)");
            consumer.accept("方法引用之实例::实例方法(Supplier):"+supplier.get());
            consumer.accept("方法引用之实例::实例方法(Function):"+function.apply(0));
            consumer.accept("方法引用之实例::实例方法(Predicate):"+predicate.test("c"));
        }
    
  • 类::类方法

    @Test
        public void demo2(){
            List<String> list= Arrays.asList("javase","hello","word");
            List<String> list2= Arrays.asList("javase","hello");
            Consumer<List<String>> consumer= Collections::sort;
            Supplier<Iterator> supplier=Collections::emptyIterator;
            Function<List<String>,List<String>> function=Collections::synchronizedList;
            BiPredicate<List<String>,List<String>> predicate=Collections::disjoint;
    
            consumer.accept(list);
            log.debug("方法引用之类::类方法(Consumer):"+list);
            log.debug("方法引用之类::类方法(Supplier):"+supplier.get());
            log.debug("方法引用之类::类方法(Function):"+function.apply(list));
            log.debug("方法引用之类::类方法(Predicate):"+predicate.test(list,list2));
        }
    
  • 类::实例方法

    @Test
        public void demo3(){
            ArrayList<String> list= new ArrayList<>(Arrays.asList("javase","hello","word"));
            BiConsumer<List<String>,Consumer> consumer= List::forEach;
            BiFunction<List<String>,Object,Integer> function=List::indexOf;
            BiPredicate<List<String>,String> predicate=List::contains;
    
            Integer javase = function.apply(list, "javase");
            log.debug("方法引用之类::实例方法(Consumer):");
            consumer.accept(list,System.out::println);
            log.debug("方法引用之类::实例方法(Function):"+javase);
            log.debug("方法引用之类::实例方法(Predicate):"+predicate.test(list,"javase"));
        }
    

6.5 构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。

抽象方法的返回值类型即为构造器所属的类的类型

  • 与函数式接口相结合,自动与函数式接口中方法兼容。
  • 格式:ClassName::new
@Test
    public void demo4(){
        Supplier<List> supplier=ArrayList::new;
        Function<Integer,Integer> function=Integer::new;
        Predicate<Boolean> predicate=Boolean::new;

        System.out.println(supplier.get());
        System.out.println(function.apply(1));
        System.out.println(predicate.test(true));
    }

6.6 数组引用

可以把数组看做是一个特殊的类,则写法与构造器引用一致。

@Test
    public void demo5(){
        Function<Integer,Integer[]> function=Integer[]::new;
        System.out.println(function.apply(2));
    }

七、Stream API

7.1 概述

  • Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一个则是Stream API。
  • Stream API ( java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
  • Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
  • 为什么要使用Stream API
    • 实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要Java层面去处理
    • Stream 和Collection 集合的区别:Collection 是一种静态的内存数据结构,而Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU 实现计算
/**
 * 1.Stream关注的是对数据的运算,与CPU打交道
 *   集合关注的是数据的存储,与内存打交道
 *
 * 2.特点
 * ①Stream 自己不会存储元素。
 * ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
 * ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
 *
 * 3.Stream 执行流程
 * ① Stream的实例化
 * ② 一系列的中间操作(过滤、映射、...)
 * ③ 终止操作
 *
 * 4.说明:
 * 4.1 一个中间操作链,对数据源的数据进行处理
 * 4.2 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
 */

在这里插入图片描述

7.2 创建

  • 1、通过 java.util.Collection.stream()/parallelStream() 方法用集合创建流
    	stream():创建顺序流。
    	parallel():把顺序流转换成并行流
    	parallelStream():创建并行流。内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求
    	
    2、使用java.util.Arrays.stream(T[] array)方法用数组创建流
    
    3、使用Stream的静态方法创建流:
    	- of(1,2,3,4)								//有限流
    	- iterate(0, (x) -> x + 3).limit(4)			//无限流
    	- generate(Math::random).limit(3)			//无限流
    
  • public class StreamAPITest {
    
        //创建 Stream方式一:通过集合
        @Test
        public void test(){
            List<Employee> employees = EmployeeData.getEmployees();
    
    //        default Stream<E> stream() : 返回一个顺序流
            Stream<Employee> stream = employees.stream();
    
    //        default Stream<E> parallelStream() : 返回一个并行流
            Stream<Employee> parallelStream = employees.parallelStream();
        }
    
        //创建 Stream方式二:通过数组
        @Test
        public void test2(){
            int[] arr = new int[]{1,2,3,4,5,6};
            //调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流
            IntStream stream = Arrays.stream(arr);
    
            Employee e1 = new Employee(1001,"Hom");
            Employee e2 = new Employee(1002,"Nut");
            Employee[] arr1 = new Employee[]{e1,e2};
    
            Stream<Employee> stream1 = Arrays.stream(arr1);
        }
        
        //创建 Stream方式三:通过Stream的of()
        @Test
        public void test3(){
            Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
        }
        
        //创建 Stream方式四:创建无限流
        @Test
        public void test4(){
    //      迭代
    //      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
            //遍历前10个偶数
            Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
    
    //      生成
    //      public static<T> Stream<T> generate(Supplier<T> s)
            Stream.generate(Math::random).limit(10).forEach(System.out::println);
        }
    }
    

7.3 中间操作

  • 中间操作
     过滤、筛选与切片
     - filter(Predicate p):从流中排除某些元素
     - distinct():去重
     - limit(long maxSize):取前maxSize个元素
     - skip(long n):跳过前n个元素
     映射
     - map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
     - flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
     排序
     - sorted():自然排序,流中元素需实现Comparable接口
     - sorted(Comparator com):Comparator排序器自定义排序
    
  • public static  final <T> Stream<T> getStream(ArrayList<T> list){
        return list.stream();
    }
    /**
     * 中间操作
     * 终止操作-遍历:forEach
     */
    @Test
    public void demo4(){
        Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa","bbb","ccc")));
        
        //中间操作:映射->排序->限制->切片->去重->过滤
        Stream<String> stringStream = stream
        .map(item -> item + item)
        .sorted().limit(3)
        .skip(0)
        .distinct()
        .filter(item -> item instanceof String);
        
        //终止操作
        stringStream.forEach(System.out::println);
    }
    

7.4 终止操作

  • 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。
     遍历
     - forEach(Consumer c):内部迭代
     匹配与查找
     - allMatch(Predicate p): 全部元素是否都符合条件
     - anyMatch(Predicate p):是否包含一个符合条件的元素
     - noneMatch(Predicate p):是否没有包含符合条件的元素
     - findFirst():匹配第一个
     - findAny():匹配任意(适用于并行流)
     - count():统计流中个数
     - max(Comparator c):返回流中最大值
     - min(Comparator c):返回流中最小值
     归约
     - reduce(T iden, BinaryOperator b):归约/聚合,返回T。
     - reduce(BinaryOperator b):归约/聚合,返回Optional。
     收集:
     collect(Collectors.toList())把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。
      - toList()
      - toSet()
      - toMap(Person::getName, p -> p)
      - 计数:counting
      - 平均值:averagingInt、averagingLong、averagingDouble
      - 最值:maxBy、minBy
      - 求和:summingInt、summingLong、summingDouble
      - 统计以上所有:summarizingInt、summarizingLong、summarizingDouble
      - partitioningBy:分区。按条件分为两个Map
      - groupingBy:分组。按参数值分为多个Map
      - joining(","):将stream中元素用特定的连接符(没有的话,则直接连接)连接成一个字符串
      - reducing:相比于stream本身的reduce方法,增加了对自定义归约的支持。
    
  • /**
         * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。
         * 匹配与查找
         */
        @Test
        public void demo5(){
            Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc")));
            //匹配与查找
    //        boolean b = stream.allMatch(item -> item instanceof String);
    //        log.debug("匹配与查找allMatch:"+b);//true
    //        boolean aaa = stream.anyMatch(item -> item.equals("aaa"));
    //        log.debug("匹配与查找anyMatch:"+aaa);//true
    //        boolean ddd = stream.noneMatch(item -> item.equals("ddd"));
    //        log.debug("匹配与查找noneMatch:"+ddd);//true
    //        Optional<String> any = stream.parallel().findAny();
    //        String s = any.get();
    //        log.debug("匹配与查找findAny:"+s);//bbb
    //        long count = stream.count();
    //        log.debug("匹配与查找count:"+count);//3
    //        Optional<String> max = stream.max((a, b) -> a.compareTo(b));
    //        String s = max.get();
    //        log.debug("匹配与查找max:"+s);//ccc
            Optional<String> min = stream.min((a, b) -> a.compareTo(b));
            String s = min.get();
            log.debug("匹配与查找min:"+s);//aaa
        }
    
    
    
    /**
         * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。
         * 归约
         */
        @Test
        public void demo6(){
            Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc")));
    //        String hello_ = stream.reduce("hello ", (a, b) -> a + b);
    //        log.debug("归约reduce:"+hello_);//hello aaabbbccc
            Optional<String> reduce = stream.reduce((a, b) -> a + b);
            String s = reduce.get();
            log.debug("归约reduce:"+s);//aaabbbccc
        }
    
    
    
    /**
         * 终止操作:从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void 。
         * 收集
         */
        @Test
        public void demo7(){
            Stream<String> stream = getStream(new ArrayList<String>(Arrays.asList("aaa", "bbb", "ccc")));
    //        List<String> collect = stream.collect(Collectors.toList());
    //        log.debug("收集Collectors.toList:"+collect.toString());//[aaa, bbb, ccc]
    
    //        Set<String> collect1 = stream.collect(Collectors.toSet());
    //        log.debug("收集Collectors.toSet:"+collect1.toString());//[aaa, ccc, bbb]
    
    //        Map<String, String> collect = stream.collect(Collectors.toMap(item -> item, item -> item));
    //        log.debug("收集Collectors.toMap:"+collect.toString());//{aaa=aaa, ccc=ccc, bbb=bbb}
    
    //        Long collect = stream.collect(Collectors.counting());
    //        log.debug("收集Collectors.counting:"+collect);//3
    
    //        Optional<String> collect = stream.collect(Collectors.maxBy((a, b) -> a.compareTo(b)));
    //        String s = collect.get();
    //        log.debug("收集Collectors.maxBy:"+s);//ccc
    
    //        Optional<String> collect = stream.collect(Collectors.minBy((a, b) -> a.compareTo(b)));
    //        String s = collect.get();
    //        log.debug("收集Collectors.minBy:"+s);//aaa
    
    //        Map<Boolean, List<String>> aaa = stream.collect(Collectors.partitioningBy(item -> item.equals("aaa")));
    //        log.debug("收集Collectors.partitioningBy:"+aaa.toString());//{false=[bbb, ccc], true=[aaa]}
    
    //        Map<String, List<String>> collect = stream.collect(Collectors.groupingBy(item -> item));
    //        log.debug("收集Collectors.groupingBy:"+collect.toString());//{aaa=[aaa], ccc=[ccc], bbb=[bbb]}
    
    //        String collect1 = stream.collect(Collectors.joining("  "));
    //        log.debug("收集Collectors.joining:"+collect1);//aaa  bbb  ccc
    
            Optional<String> collect = stream.collect(Collectors.reducing((a, b) -> a + b));
            String s = collect.get();
            log.debug("收集Collectors.reducing:"+s);//aaabbbccc
        }
    

八、Optional类

8.1、Optional类的介绍

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。

  • Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。
  • Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  • Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  • 创建Optional类对象的方法:
    • Optional.of(T t) : 创建一个Optional 实例,t必须非空;通常与get()配合使用
    • Optional.empty() : 创建一个空的Optional 实例
    • Optional.ofNullable(T t):t可以为null。通常与orElse()配合使用
  • 判断Optional容器中是否包含对象:
    • boolean isPresent() : 判断是否包含对象
    • void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。
  • 获取Optional容器的对象:
    • T get(): 如果调用对象包含值,返回该值,否则抛异常。通常与of()配合使用
    • T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。通常与ofNullable()配合使用
    • T orElseGet(Supplier<? extends T> other) :如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
    • T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。

1、Boy类

public class Boy {
    private Girl girl;

    public Boy() {
    }

    public Boy(Girl girl) {
        this.girl = girl;
    }

    public Girl getGirl() {
        return girl;
    }

    public void setGirl(Girl girl) {
        this.girl = girl;
    }

    @Override
    public String toString() {
        return "Boy{" +
                "girl=" + girl +
                '}';
    }
}

2、Girl类

public class Girl {
    private String name;

    public Girl() {
    }

    public Girl(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Girl{" +
                "name='" + name + '\'' +
                '}';
    }
}

3、测试类

import org.junit.Test;
import java.util.Optional;

/**
 * Optional类:为了在程序中避免出现空指针异常而创建的。
 *
 * 常用的方法:ofNullable(T t)
 *           orElse(T t)
 */
public class OptionalTest {
    /**
     * Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
     * Optional.empty() : 创建一个空的 Optional 实例
     * Optional.ofNullable(T t):t可以为null
     */
    @Test
    public void test(){
        Girl girl = new Girl();
//        girl = null;
        //of(T t):保证t是非空的
        Optional<Girl> optionalGirl = Optional.of(girl);
    }

    @Test
    public void test2(){
        Girl girl = new Girl();
//        girl = null;
        //ofNullable(T t):t可以为null
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println(optionalGirl);
        //orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.
        //如果内部的t是空的,则返回orElse()方法中的参数t1.
        Girl girl1 = optionalGirl.orElse(new Girl(""));
        System.out.println(girl1);
    }
}

8.2、Optional类的使用举例

1、测试类

import org.junit.Test;
import java.util.Optional;

/**
 * Optional类:为了在程序中避免出现空指针异常而创建的。
 *
 * 常用的方法:ofNullable(T t)
 *           orElse(T t)
 */
public class OptionalTest {

    @Test
    public void test3(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName(boy);
        System.out.println(girlName);
    }

    private String getGirlName(Boy boy) {
        return boy.getGirl().getName();
    }

    //优化以后的getGirlName():
    public String getGirlName1(Boy boy){
        if(boy != null){
            Girl girl = boy.getGirl();
            if(girl != null){
                return girl.getName();
            }
        }
        return null;
    }

    @Test
    public void test4(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName1(boy);
        System.out.println(girlName);
    }

    //使用Optional类的getGirlName():
    public String getGirlName2(Boy boy){

        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        //此时的boy1一定非空
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("朱淑贞")));

        Girl girl = boy1.getGirl();

        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        //girl1一定非空
        Girl girl1 = girlOptional.orElse(new Girl("阿青"));

        return girl1.getName();
    }

    @Test
    public void test5(){
        Boy boy = null;
        boy = new Boy();
        boy = new Boy(new Girl("李清照"));
        String girlName = getGirlName2(boy);
        System.out.println(girlName);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JavaSE】jdk8新特性 的相关文章

随机推荐

  • R、Rstudio和Rtools的安装(以4.3.0版本为例)

    1 R的安装 下载地址 The Comprehensive R Archive Network tsinghua edu cn 这里下载的是4 3 0版本 选择Windows版本 下载后选择路径进行安装 默认选项即可 2 Rtools的安装
  • LabVIEW2018安装与使用

    安装 https blog csdn net m0 38106923 article details 88654150 每一个labview程序叫做一个vi 文件 新建vi 前面板 放一些控件 eg 输入控件 输出控件 显示控件 右键 选择
  • HttpMessageNotReadableException: JSON parse error: Unexpected character (‘“‘ (code 34)): was expecti

    作者 我弟 接口请求报错 2022 07 16 16 41 01 579 WARN 18820 nio 9002 exec 3 w s m s DefaultHandlerExceptionResolver Resolved org spr
  • Redis数据库安装

    1 redis安装包下载 redis安装包下载地址 https github com MicrosoftArchive redis releases windows下载msi安装包即可 2 安装redis 下载完成后 点击进行安装 按默认配
  • IT项目管理 — 作业7

    题目 Tony Prince 和他的团队正在做一个娱乐和健康方面的项目 他们被要求修改现有的成本估计 以便能有一个可靠的评价项目绩效的基线 进度和成本目标是在 6 个月内在 200 000 美元的预算下完成项目 准备和打印一页类似于图 7
  • 有什么好用的Angular插件推荐吗?

    10 个最受欢迎的 Angular 库 一 Angular Material Angular Material 是由 Google 开发的一款工具 是适合与 Angular 框架一起使用的 UI UX 组件库 Angular Materia
  • 实现DNS主从复制、子域、转发、智能DNS

    主从复制 前提准备 关闭SElinux 关闭防火墙 时间同步 环境说明 Centos7 ip地址 dns master 10 0 0 100 dns slave 10 0 0 103 web 10 0 0 101 目的 搭建DNS主从服务器
  • 计算机原理-结构组成

    cpu 中央处理器 程序控制 操作控制 时间控制 数据处理 运算器 算数逻辑单元ALU 逻辑运行 累加计算器AC 为alu提供工作区 数据缓存寄存器 DR 暂存指令和数据 状态条件寄存器PSW 保存指令条件码 控制器 程序计数器PC 指令计
  • python华为OD机试-进制转换-(5)

    题目5 题目描述 写出一个程序 接受一个十六进制的数 输出该数值的十进制表示 输入描述 输入一个十六进制的数值字符串 注意 一个用例会同时有多组输入数据 请参考帖子https www nowcoder com discuss 276处理多组
  • Matlab中的画图函数

    目录 一 二维曲线和图形 1 二维图像基本命令plot 1 曲线线型 颜色和标记点类型 2 设置曲线线宽 标记点大小 标记点边框颜色和标记点填充颜色等 3 坐标轴设置 4 坐标轴刻度设置 5 图例 6 更多的设置 二 图形的控制与表现 1
  • spring-MVC__spring__hibernate整合值hibernate的配置文件 (hibernate.cfg.xml)

  • QT-样式表

    Qt样式表是一个可以自定义部件外观的十分强大的机制 除了那些能够通过子类化QStyle更改的外观 其余的都可以使用Qt样式表来美化 Qt样式表的概念 术语和语法都受到了HTML的层叠样式表 Cascading Style Sheets CS
  • Ubuntu使用darknet实现YOLOv4-tiny预训练模型测试+训练自己的数据集+评估自己的模型

    文章目录 1 使用YOLOv4 tiny预训练模型 2 训练自己的数据集 2 1 建立yolov4 tiny数据格式 2 2 开始训练 2 3 多GPU训练 3 评估自己的模型 参考博客 YOLOv4 tiny的原理本文不做讲解 只有应用方
  • 黑马程序员SSM-Spring学习笔记

    学完Spring之后是SpringMVC 文章目录 前言 一 注解开发 1 1 注解开发定义bean 1 2纯注解开发 1 3bean作用范围 1 4依赖注入 自动装配 1 5 第三方bean管理 1 6 总结 二 Spring整合MyBa
  • qt槽函数如何传递多个参数_Qt 信号槽如何传递参数(或带参数的信号槽)

    标签 信号槽如何传递参数 或带参数的信号槽 利用Qt进行程序开发时 有时需要信号槽来完成参数传递 带参数的信号槽在使用时 有几点需要注意的地方 下面结合实例进行介绍 第一点 当信号与槽函数的参数数量相同时 它们参数类型要完全一致 signa
  • LeetCode 27.移除元素

    文章目录 题目分析 解题思路 思路1 暴力求解 遍历 接口源码 思路2 空间换时间 接口源码 思路3 双指针 快慢指针 接口源码 题目链接 LeetCode 27 移除元素 题目分析 给你一个数组 nums 和一个值 val 你需要 原地
  • 推荐算法实战项目:FNN 原理以及案例实战(附完整 Python 代码)

    本文要介绍的是FNN模型 出自于张伟楠老师于2016年发表的论文 Deep Learning over Multi field Categorical Data 论文提出了两种深度学习模型 分别叫做FNN Factorisation Mac
  • JMeter接口压测和性能监测

    引言 今天我来和大家分享一篇关于JMeter接口压测和性能监测的文章 在现代互联网时代 应用程序的性能已经成为了一个非常重要的问题 并且对于许多公司的生存和发展都起着至关重要的作用 而在这其中 JMeter是一个非常实用的工具 可以帮助我们
  • html5养树游戏源码,奥日小屋:寻找精灵之树

    大家好我是Receiver 又到了一年一度的夏促时间啦 不知道如何剁手的盒友可以考虑入坑 奥日与黑暗森林 哟 作为一款15年的游戏放在现在来看仍然有惊艳的画风 音乐与游戏性 夏促期间五折史低 今天给大家带来的是寻找银之树的流程攻略 另外奥日
  • 【JavaSE】jdk8新特性

    尚硅谷JavaSE笔记合集 文章名 链接 JavaSE 异常 文章地址 JavaSE 常用类 String LocalDateTime 文章地址 JavaSE 枚举 文章地址 JavaSE 注解 文章地址 JavaSE 集合框架 文章地址