JAVA-Optional型

菜鸟为了巩固所写

目录

一、概述

1、讨厌的NullPointerException

2、Optional类型简介

二、使用Optional

1、构建Optional实例

综合示例1

示例1

        使用Optional。示例2

        有不少 Stream API 函数直接 返回 Optional 对象,以下是一个示例:

三、针对原始数据的Optional

1、OptionalInt

四、类型转换


一、概述

1、讨厌的NullPointerException

  • 由于Stream API 中经常需要“级联”多个操作,因此,如果中间某个操作遇到 null 引用时,如何处理它是个麻烦事。
  • 默认情况下,如果针对null 引用调用某个类的实例方法, JVM 会抛出NullPointerException ,如果不做妥善处理 ,这个异常可能 会“打断”流处理管线。
  • 为了解决这个问题,Java 8 专门 引入了一个 Optional<T> 类。
     

2、Optional类型简介

  • Optional对象是一个“可能为 null的对象。
  • 所有那些有可能返回一个null 引用的操作,都应该返回一个 Optional 对象。
  • Optional对象定义了一个isPresent 方法用于确定它是否包容一个有效的值。如果值有效,可以调用它的 get 方法提取出这个值。
  • 如果isPresent() 返回 false ,代码又尝试调用它的 get() 方法,JVM 会抛出一个 NoSuchElementException 。

二、使用Optional

1、构建Optional实例

综合示例1

package com.jinxuliang;

import java.util.Optional;
import java.util.stream.Stream;

public class CreateOptionalDemo {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Optional", "type", null, "", "is", "very", "useful");
        stream.map(str -> processString(str, 2)) //截取两个字符
                .filter(str -> str.isPresent())  //过滤掉空引用
                .forEach(System.out::println); //输出结果
    }

    //截取指定长度的字符串
    public static Optional<String> processString(String string, int length) {
        if (string == null || length <= 0 || string.length() < length) {
            return Optional.empty();
        }
		//构建Optional对象
        return Optional.of(string.substring(0, length));
    }
}

        最简单的构建Optional 对象的方法是使用其 of() 方法,另一个empty() 方法用于构建一个 “空的 Optional 对象。

示例1
    //截取指定长度的字符串
    public static Optional<String> processString(String string, int length) {
        if (string == null || length <= 0 || string.length() < length) {
            return Optional.empty();
        }
		//构建Optional对象
        return Optional.of(string.substring(0, length));
    }

        另一个有用的方法是Optional.ofNullable(obj) 。当obj==null 时,此方法返回 Optional.empty() ,否则返回 Optional.Of(obj) 。

        使用Optional。示例2

        返回Optional 对象的函数,可以直接用于 map 函数中:

    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Optional", "type", null, "", "is", "very", "useful");
        stream.map(str -> processString(str, 2)) //截取两个字符
                .filter(str -> str.isPresent())  //过滤掉空引用
                .forEach(System.out::println); //输出结果
    }

        有不少 Stream API 函数直接 返回 Optional 对象,以下是一个示例:

package com.jinxuliang;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class UseOptional {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(106, 234, 39, 134, 19, 80);
        //min函数(还有max函数),返回Optional
        var result = numbers.stream()
                .min(Comparator.naturalOrder());
        System.out.println(result.get());//19

        //of函数返回Optional
        Optional<String> str = Optional.of("Hello");
        //isPresent()可以简写为ifPresent
        str.ifPresent(System.out::println);

        //map函数返回Optional
        var stringLength= str.map(String::length);
        stringLength.ifPresent(System.out::println);
    }
}

三、针对原始数据的Optional

        一般来说,只有引用类型才有null 值,原始数据类型的变量,比如 int ,一定义就有值了,不会出现 null 情况。

        但原始数据类型的包装类,比如Integer ,使用它们定义的变量,则是有可能为 null 的。为此, JDK 中为它们提供了专门的 Optional 类型 OptionalInt 、 OptionalDouble 和OptionalLong 以 避免发生不必要的装箱和拆箱操作。

1、OptionalInt

        针对原始数据类型,JDK 提供了 OptionalInt, OptionalLong 和OptionalDouble 三个类,拥有 getAsXXX() 的方法,下面以 OptionalInt 为例介绍其用法:

package com.jinxuliang.model;

public class OrderClient {
    private int id;
    private String name;
    private String address;

    public OrderClient(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "OrderClient{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
package com.jinxuliang;

import com.jinxuliang.model.OrderClient;

import java.util.Comparator;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class OptionalIntTest {
    public static void main(String[] args) {

        // 创建一个“空的”OptionalInt实例
        OptionalInt empty = OptionalInt.empty();
        // 创建一个 OptionalInt实例,保存数值287
        OptionalInt number = OptionalInt.of(287);
        //从OptionaInt实例中提取数据的方法
        if (number.isPresent()) {
            int value = number.getAsInt();
            System.out.println("Number is " + value);
        } else {
            System.out.println("Number is absent.");
        }

        // 一些Stream API方法,返回OptionalInt
        OptionalInt numbers = IntStream.of(1, 10, 37, 20, 31)
                .filter(n -> n % 2 == 1).max();
        if (numbers.isPresent()) {
            int value = numbers.getAsInt();
            System.out.println("最大值为: " + value);
        } else {
            System.out.println("流为空");
        }

        var client = getOrderClient();
        //client有可能为null,使用orElse指定默认值
        String name = client.map(OrderClient::getName).orElse("无名氏");
        System.out.println(name);



    }

    //用Optional封装有可能为null值的方法
    private static Optional<OrderClient> getOrderClient() {
        var ranValue = new Random().nextInt(100);
        if (ranValue % 2 == 0) {
            return Optional.empty();
        } else {
            var client = new OrderClient(ranValue,
                    "client" + ranValue);
            return Optional.of(client);
        }
    }
}

四、类型转换

        Optional类中定义有一个 map 方法,可以对结果进行类型 转换,得到 另一个 Optional 对象:

package com.jinxuliang;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class UseOptional {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(106, 234, 39, 134, 19, 80);
        //min函数(还有max函数),返回Optional
        var result = numbers.stream()
                .min(Comparator.naturalOrder());
        System.out.println(result.get());//19

        //of函数返回Optional
        Optional<String> str = Optional.of("Hello");
        //isPresent()可以简写为ifPresent
        str.ifPresent(System.out::println);

        //map函数返回Optional
        var stringLength= str.map(String::length);
        stringLength.ifPresent(System.out::println);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值