java1.8新特性入门级讲解

Java1.8新特性

java1.8引入了许多的特性,在此我们主要讨论一下几点:

  • 接口静态方法

  • 接口默认方法 : 默认方法就是一个在接口里面有了一个或多个实现的方法。

  • 函数式接口: 一个在接口只有一个待实现的方法。 (重要)

  • Lambda 表达式: Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。 (重要)

  • Stream API: 新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。 (重要)

  • Date Time API: 加强对日期与时间的处理。

  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

接口静态方法

为什么接口要支持静态方法

接口中的静态方法背后的思想是提供一种简单的机制,允许通过将相关的方法内聚在接口中,而不必创建新的对象

抽象类也可以做同样的事情。主要的区别在于抽象类可以有构造函数、成员变量和方法。

推荐把和只和接口相关的静态utility方法放在接口中(提高内聚性),而不需要额外创建一些utility类专门去放置这些方法。

interface NewInterface { 

    // 静态方法
    static void hello() 
    { 
        System.out.println("Hello, New Static Method Here"); 
    } 

    // 抽象方法 
    void overrideMethod(String str); 
} 

接口默认方法

Java 8 新增了接口的默认方法。

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个 default 关键字即可实现默认方法。

为什么要有这个特性?

首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

JDK8 中接口默认方法有什么用

以前创建了一个接口,并且已经被大量的类实现。
如果需要再扩充这个接口的功能加新的方法,就会导致所有已经实现的子类需要重写这个方法。
如果在接口中使用默认方法就不会有这个问题。
所以从 JDK8 开始新加了接口默认方法,便于接口的扩展。

例子:
public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}

函数式接口与Lambda表达式

为什么我要把这两个放一起讲呢?是因为Lambda表达式的原理就是调用的函数式接口

函数式接口与Lambda的关联

我以Runnable举例,这是一个最常见的函数式接口:

// 函数式接口的注解 @FunctionalInterface 其实也可以不加,而加上的理由:1、为了美观、易读 2、加上该注解能够更好地让编译器进行检查。
@FunctionalInterface
// 这个接口里面只有一个实现方法,被我们成为函数式接口
public interface Runnable {
    public abstract void run();
}

作用:可以使用Lambda来简化函数式接口

    public static void main(String[] args) {
        // 就用Runable实现run的方法,启动线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这个代码看着就很麻烦");
            }
        }).start();
        
        // Lambda 表达式 是用来简化函数式接口的
        new Thread(()->{
            System.out.println("这个看着就很清爽");
        }).start();
    }

好,经过以上的两个案例,想必大家多少理解了函数式接口与Lambda是个啥玩意,那么下面我来说一下四大函数式接口,这里很重要,与Stream流息息相关

四大函数式接口

1、Function <T,R>:函数式接口,有参有返回值

我们先来看源码:安装1、2、3、的顺序读

@FunctionalInterface
// 1、相信大家看了也摸不着头脑 这样
public interface Function<T, R> {
    // 3、我们就看这里,这里不就是说,给一个T的类,返回一个R的类吗?T与R是泛型,代指类
    R apply(T t);

    // 2、下面的这些有default关键字,是接口默认方法,所以我们就不看了,最后一个是接口静态方法,不是我们要找的函数式接口方法
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
好,上一步不理解没关系,这里我们看案例:
    public static void main(String[] args) {
        // 这里就是通过function方法把String的值转换为Integer类型,看着就很多
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String o) {
                return Integer.parseInt(o);
            }
        };
        System.out.println(function.apply("21"));

        // 因为这是一个函数式接口,我们用Lambda简化一下
        Function<String, Integer> function2 = (str)->{return Integer.parseInt(str);};
        System.out.println(function2.apply("35"));

        // 再简化,这里主要讲的函数式接口的使用,函数式接口与Lambda的关系,之后会将Lambda表达式的
        Function<String, Integer> function3 = Integer::parseInt;
        System.out.println(function3.apply("67"));

    }

看一下输出:

在这里插入图片描述

2、Predicate < T >: 断言型接口,有参有返回值,返回值是boolean类型

我们先来看源码:

@FunctionalInterface
public interface Predicate<T> {
    // 还是只看这个,意思就很明确了,传入一个泛型然后返回一个boolean类型
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}
好,看案例:
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer o) {
                if (o>10){
                    return true;
                }else {
                    return false;
                }
            }
        };
        System.out.println("predicate--1==>"+predicate.test(1));
        System.out.println("predicate--11==>"+predicate.test(11));

        //因为这是一个函数式接口,我们用Lambda简化一下
        Predicate<Integer> predicate2 = (o)->{
            if (o>10){
                return true;
            }else {
                return false;
            }
        };
        System.out.println("predicate2--15==>"+predicate2.test(15));

看结果:

在这里插入图片描述

3、Consumer < T >:消费型接口,有参无返回值

看源码:

@FunctionalInterface
public interface Consumer<T> {
    // 还是看这个 不就是说放一个值进来 没有返回值嘛
    void accept(T t);


    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
看案例:
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String o) {
                System.out.println("胖虎打"+o);
            }
        };
        consumer.accept("大熊");

		// Lambda简化
        Consumer<String> consumer2 = str ->{
            System.out.println("大熊打"+str);
        };
        consumer2.accept("胖虎");

结果:

在这里插入图片描述

4、Supplier < T >:供给型接口,无参有返回值

看源码:

@FunctionalInterface
public interface Supplier<T> {
    // 没有传参返回一个 T 类型的值
    T get();
}
看案例:
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "就没有返回值";
            }
        };
        System.out.println(supplier.get());
        
        //简化
        Supplier<Integer> supplier2 = ()->{ return 1024; };
        System.out.println(supplier2.get());

结果:

在这里插入图片描述

Lambda表达式:

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法

lambda 表达式的语法格式如下:

(parameters) -> expression

(parameters) ->{ statements; }

lambda表达式的重要特征:
  • **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
  • **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
  • **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

Lambda 表达式简单实例

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

案例:

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
    // 这也是函数式接口 只不过是类里面的接口
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

输出结果:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

这里我就带大家过一遍,Lambda知识点很多,入门或者正常使用的话,看我这个就足够了,如果还行深究就可以看一下这篇文章:Java-lambda表达式入门看这一篇就够了 - 腾讯云开发者社区-腾讯云 (tencent.com)

Stream流:

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

按照装我的理解,这玩意就是用来处理集合的,而且非常的高效

生成流

在 Java 8 中, 集合接口有两个方法来生成流:

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

各种API:

forEach

Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

map

map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

filter

filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();

limit

limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

并行(parallel)程序

parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

我们可以很容易的在顺序运行和并行直接切换。

Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

统计

另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
 
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
 
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

我的案例:

public class Demo {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        Student student = new Student(18,"张三",1);
        list.add(student);
        student = new Student(13,"张三",1);
        list.add(student);
        student = new Student(21,"李四",1);
        list.add(student);
        student = new Student(10,"小红",0);
        list.add(student);
        student = new Student(25,"大红",0);
        list.add(student);
        // 我在里面list存放了 四个对象
        // 1、18岁男性张三
        // 2、21岁男性李四
        // 3、10岁女性小红
        // 4、25岁女性大红

        // 案例一、现在我要找所有的女性
        System.out.println("案例一、现在我要找所有的女性");
        List<Student> collect = list.stream().filter(x -> {
            return x.getSex() == 0;
        }).collect(Collectors.toList());
        for (Student student1 : collect) {
            System.out.println(student1);
        }
        System.out.println("简化案例一");
        // 案例一、简化
        list.stream().filter(x->{return x.getSex()==0;}).collect(Collectors.toList()).forEach(System.out::println);

        // 案例二、所有人名字
        System.out.println("案例二、所有人名字");
        list.stream().map(Student::getName).collect(Collectors.toList()).forEach(x->{
            System.out.print(x+"、");
        });
        System.out.println();
        System.out.println("案例二、所有人名字且不重复");
        list.stream().map(Student::getName).collect(Collectors.toSet()).forEach(x->{
            System.out.print(x+"、");
        });
        System.out.println();
        System.out.println("案例三、所有人名字且只要三条条数据");
        list.stream().map(Student::getName).limit(3).collect(Collectors.toList()).forEach(x->{
            System.out.print(x+"、");
        });
    }
}
class Student{
    private int age;
    private String name;
    private int sex; // 0为女 1为男

    public Student(int age, String name, int sex) {
        this.age = age;
        this.name = name;
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }


    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", sex=" + sex +
                '}';
    }
}
这里我就带大家过一遍,Stream知识点很多,入门或者正常使用的话,看我这个就足够了,如果还行深究就可以看一下这篇文章:Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合_云深i不知处的博客-CSDN博客_java stream 分组聚合

日期时间 API

Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

  • Local(本地) − 简化了日期时间的处理,没有时区的问题。
  • Zoned(时区) − 通过制定的时区处理日期时间。

新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

本地化日期时间 API

LocalDate/LocalTime 和 LocalDateTime 类可以在处理时区不是必须的情况。代码如下:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;
 
public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testLocalDateTime();
   }
    
   public void testLocalDateTime(){
    
      // 获取当前的日期时间
      LocalDateTime currentTime = LocalDateTime.now();
      System.out.println("当前时间: " + currentTime);
        
      LocalDate date1 = currentTime.toLocalDate();
      System.out.println("date1: " + date1);
        
      Month month = currentTime.getMonth();
      int day = currentTime.getDayOfMonth();
      int seconds = currentTime.getSecond();
        
      System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds);
        
      LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
      System.out.println("date2: " + date2);
        
      // 12 december 2014
      LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
      System.out.println("date3: " + date3);
        
      // 22 小时 15 分钟
      LocalTime date4 = LocalTime.of(22, 15);
      System.out.println("date4: " + date4);
        
      // 解析字符串
      LocalTime date5 = LocalTime.parse("20:15:30");
      System.out.println("date5: " + date5);
   }
}

输出结果:

当前时间: 2016-04-15T16:55:48.668
date1: 2016-04-15
月: APRIL, 日: 15, 秒: 48
date2: 2012-04-10T16:55:48.668
date3: 2014-12-12
date4: 22:15
date5: 20:15:30

使用时区的日期时间API

如果我们需要考虑到时区,就可以使用时区的日期时间API:

import java.time.ZonedDateTime;
import java.time.ZoneId;
 
public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testZonedDateTime();
   }
    
   public void testZonedDateTime(){
    
      // 获取当前时间日期
      ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");
      System.out.println("date1: " + date1);
        
      ZoneId id = ZoneId.of("Europe/Paris");
      System.out.println("ZoneId: " + id);
        
      ZoneId currentZone = ZoneId.systemDefault();
      System.out.println("当期时区: " + currentZone);
   }
}

输出结果为:

date1: 2015-12-03T10:15:30+08:00[Asia/Shanghai]
ZoneId: Europe/Paris
当期时区: Asia/Shanghai

Optional 类

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常。

类声明

以下是一个 java.util.Optional 类的声明:

public final class Optional<T>
extends Object

类方法

序号方法 & 描述
1**static Optional empty()**返回空的 Optional 实例。
2**boolean equals(Object obj)**判断其他对象是否等于 Optional。
3**Optional filter(Predicate<? super predicate)**如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
4** Optional flatMap(Function<? super T,Optional> mapper)**如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
5**T get()**如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
6**int hashCode()**返回存在值的哈希码,如果值不存在 返回 0。
7**void ifPresent(Consumer<? super T> consumer)**如果值存在则使用该值调用 consumer , 否则不做任何事情。
8**boolean isPresent()**如果值存在则方法会返回true,否则返回 false。
9**Optional map(Function<? super T,? extends U> mapper)**如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
10**static Optional of(T value)**返回一个指定非null值的Optional。
11**static Optional ofNullable(T value)**如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
12**T orElse(T other)**如果存在该值,返回值, 否则返回 other。
13**T orElseGet(Supplier<? extends T> other)**如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
14** T orElseThrow(Supplier<? extends X> exceptionSupplier)**如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
15**String toString()**返回一个Optional的非空字符串,用来调试

注意: 这些方法是从 java.lang.Object 类继承来的。

Optional 实例

我们可以通过以下实例来更好的了解 Optional 类的使用:

import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允许传递为 null 参数
      Optional<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      // Optional.isPresent - 判断值是否存在
        
      System.out.println("第一个参数值存在: " + a.isPresent());
      System.out.println("第二个参数值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,返回它,否则返回默认值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 获取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}

输出结果为:

第一个参数值存在: false
第二个参数值存在: true
10

以上部分内容参照:

Java 8 日期时间 API | 菜鸟教程 (runoob.com)

Nullable(value1);

  // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
  Optional<Integer> b = Optional.of(value2);
  System.out.println(java8Tester.sum(a,b));

}

public Integer sum(Optional a, Optional b){

  // Optional.isPresent - 判断值是否存在
    
  System.out.println("第一个参数值存在: " + a.isPresent());
  System.out.println("第二个参数值存在: " + b.isPresent());
    
  // Optional.orElse - 如果值存在,返回它,否则返回默认值
  Integer value1 = a.orElse(new Integer(0));
    
  //Optional.get - 获取值,值需要存在
  Integer value2 = b.get();
  return value1 + value2;

}
}


输出结果为:

> 第一个参数值存在: false
> 第二个参数值存在: true
> 10





## 以上部分内容参照:

[Java 8 日期时间 API | 菜鸟教程 (runoob.com)](https://www.runoob.com/java/java8-datetime-api.html)

[Java 8 Optional 类 | 菜鸟教程 (runoob.com)](https://www.runoob.com/java/java8-optional-class.html)
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我认不到你

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

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

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

打赏作者

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

抵扣说明:

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

余额充值