Java8Optional笔记240220

Java8Optional

Optional并不是提供功能, 而是提供一种null处理的规范,大家都用的话可能代码阅读起来容易一点? 源码很简单

获取实例(包装值)的3个方法: ofNullable(of(empty()

构造器是private的, 有3个获取实例的静态方法

ofNullable(of(empty()

  • Optional<指定类>op= Optional.ofNullable(指定类实例); //可接受null, 但null在get()仍然会抛异常
  • Optional<指定类>op= Optional.of(指定类实例); // null则抛异常, return new Optional<>(Objects.requireNonNull(value)); 直接调用Object的requireNonNull方法
  • Optional<指定类>op= Optional.empty(指定类实例); // 返回强制转换的 private static final Optional<?> EMPTY = new Optional<>(null);

判断值是否为null的两个方法: isPresent()isEmpty()

isPresent()isEmpty()

  • isEmpty() 源码return value == null;
  • isPresent() 源码return value != null;
    is 开头,还有个以 if开头的ifPresent( 方法可用拉姆达在有值时才执行

取值的5个方法: get()orElseorElseGetorElseThrow乘2

get()orElseorElseGetorElseThrow两个

  • get() null则抛异常 和 orElseThrow() 一样
  • orElse(null替代品) null则返回替代品
  • orElseGet(()=>{return null替代品;})orElseGet(()=>null替代品) null则返回替代品, 功能和orElse一样, 写法不同
  • orElseThrow() null则抛异常 和 get() 一样
  • orElseThrow(()->new Exception("自定义异常")); // 取值, 值空则抛自定义的异常;
get() 和 orElseThrow() 相同, jdk17源码对比
java 复制代码
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
java 复制代码
    public T orElseThrow() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

get() 和 orElseThrow() 原理完全相同, onElseThrow()是Jdk10定义的, get()是8

判断有值时回调的两个方法: ifPresentifPresentOrElse

ifPresentifPresentOrElse

  • ifPresent(值->{有值时执行的代码})
  • ifPresentOrElse(值->{有值时执行的代码} , new Thread(()->{无值时执行的代码}))

ifPresentOrElse(... 是java9新增的方法, 个人觉得不错, 明确了有值时做什么,值空时做什么.

下面是ifPresentifPresentOrElse的源码对比, 来自java17

java 复制代码
    public void ifPresent(Consumer<? super T> action) {
        if (value != null) {
            action.accept(value);
        }
    }

    /**
     * If a value is present, performs the given action with the value,
     * otherwise performs the given empty-based action.
     *
     * @param action the action to be performed, if a value is present
     * @param emptyAction the empty-based action to be performed, if no value is
     *        present
     * @throws NullPointerException if a value is present and the given action
     *         is {@code null}, or no value is present and the given empty-based
     *         action is {@code null}.
     * @since 9
     */
    public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
        if (value != null) {
            action.accept(value);
        } else {
            emptyAction.run();
        }
    }

其它回调 filter , map , flatMap , or

  • filter(v->条件)filter(v->{return 新v;} //有值且真返自己, null值或假返empty();
  • map(v->新v)filter(v->{return 新v;} //有值返新值新Optional, null值返empty(); 参数和flatMap不一样, 逻辑一样
  • flatMapp(v->Optional.of("新值新Optional"))) //有值返新值新Optional, null值返empty(); 参数和map不一样. 逻辑一样
  • or(()->Optional.of("新Optional包装的null替代品")) //有值返自己, null值返新Optional包装的null替代品; 来自java9

Java9新增的 ifPresentOrElseorstream

ifPresentOrElseor 上面已经讲过
stream就是调用Stream的发方法, 参考Stream

java 复制代码
    public Stream<T> stream() {
        if (!isPresent()) {
            return Stream.empty();
        } else {
            return Stream.of(value);
        }
    }

测试演示代码

测试及演示代码1
java 复制代码
import java.util.Optional;

import static java.lang.System.out;

public class T2402200637 {
	
	public static void main(String[] arguments){
		try {
			
			pln("hello你好");
			pln("");
			pln(null);
			
		}catch(Exception e) {e.printStackTrace();}
	}
	
	static void pln(Object o) throws Exception{
		hr();hr();hr();
		out.println("原始值="+o);
		Optional<Object>op = null;

		
		
		hr("ofNullable(o)");
		
		
		
		op = Optional.ofNullable(o); //可接受null, 但null在get()仍然会抛异常
		out.println("isEmpty()="+op.isEmpty());    //  isEmpty()  源码return value == null;
		out.println("isPresent="+op.isPresent());  //  isPresent()源码return value != null;
		try {
			Object o2 = op.get();  // 取值, 值空则抛throw new NoSuchElementException("No value present"); 自jdk8. jdk10定义的orElseThrow()和它源码一模一样
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("get()抛的"); }
		out.println(op.orElse("空指针默认值"));     //  orElse(    源码public T orElse(T other) {return value != null ? value : other;}
		out.println(op.orElseGet(()->{return "用Supplier实现的空指针默认值";}));
		out.println(op.orElseGet(()->"也可以省略return和分号大括号写成这样的:用Supplier实现的空指针默认值"));
		try {
			Object o2 = op.orElseThrow();  // 取值, 值空则抛throw new NoSuchElementException("No value present"); 和get()一模一样
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		try {
			Object o2 = op.orElseThrow(()->new Exception("自定义异常"));  // 取值, 值空则抛自定义的异常;
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		op.ifPresent(v->{out.println("因为值不为null,所以执行了 ifPresent(Consumer<? super T> action) 值为:"+v);});  //如果不null就执行拉姆达
		op.ifPresentOrElse(
				v->{out.println("因为值不为null,所以ifPresentOrElse(执行了第一个参数的拉姆达,如同ifPresent方法,值为:"+v);}
				,
				new Thread(()->{out.println("看到这句说明值null, 如果null值则ifPresentOrElse执行第二个参数的Runnable, 因为新起线程,所以不会阻塞. "); })
				);
		out.println("op.filter(v->true) 的结果:" + op.filter(v->true));    //有值且真返自己, null值或假返empty();
		out.println("op.filter(v->false)的结果:" + op.filter(v->false));   //有值且真返自己, null值或假返empty();
		out.println("op.map(v->\"新值\")的结果:" + op.map(v->"新值"));   //有值返新值新Optional, null值返empty();  参数和flatMap不一样, 逻辑一样
		out.println("op.flatMap(v->Optional.of(\"新值新Optional\")的结果:" + op.flatMap(v->Optional.of("新值新Optional")));   //有值返新值新Optional, null值返empty(); 参数和map不一样. 逻辑一样
		out.println("op.or(()->Optional.of(\"新Optional包装的null替代品\")的结果:" + op.or(()->Optional.of("新Optional包装的null替代品")));   //有值返自己, null值返新Optional包装的null替代品; 
		
		
		
		hr("of(o)");
		
		
		
		try {
			op = Optional.of(o);  // null则抛异常, return new Optional<>(Objects.requireNonNull(value));
		}catch(Exception e) {e.printStackTrace(out);  out.println("of(实例)抛的, 因为实例为空...再of"); op=Optional.of("因为上次of(null),这里再of(保证不空)"); }
		out.println("isEmpty()="+op.isEmpty());    //  isEmpty()  源码return value == null;
		out.println("isPresent="+op.isPresent());  //  isPresent()源码return value != null;
		try {
			Object o2 = op.get();  // 取值, 值空则抛throw new NoSuchElementException("No value present");
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("get()抛的"); }
		out.println(op.orElse("空指针默认值"));     //  orElse(    源码public T orElse(T other) {return value != null ? value : other;}
		out.println(op.orElseGet(()->{return "用Supplier实现的空指针默认值";}));
		out.println(op.orElseGet(()->"也可以省略return和分号大括号写成这样的:用Supplier实现的空指针默认值"));
		try {
			Object o2 = op.orElseThrow();  // 取值, 值空则抛throw new NoSuchElementException("No value present");
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		try {
			Object o2 = op.orElseThrow(()->new Exception("自定义异常"));  // 取值, 值空则抛自定义的异常;
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		op.ifPresent(v->{out.println("因为值不为null,所以执行了 ifPresent(Consumer<? super T> action) 值为:"+v);});  //如果不null就执行拉姆达
		op.ifPresentOrElse(
				v->{out.println("因为值不为null,所以ifPresentOrElse(执行了第一个参数的拉姆达,如同ifPresent方法,值为:"+v);}
				,
				new Thread(()->{out.println("看到这句说明值null, 如果null值则ifPresentOrElse执行第二个参数的Runnable, 因为新起线程,所以不会阻塞. "); })
				);
		out.println("op.filter(v->true) 的结果:" + op.filter(v->true));    //有值且真返自己, null值或假返empty();
		out.println("op.filter(v->false)的结果:" + op.filter(v->false));   //有值且真返自己, null值或假返empty();
		out.println("op.map(v->\"新值\")的结果:" + op.map(v->"新值"));   //有值返新值新Optional, null值返empty();  参数和flatMap不一样, 逻辑一样
		out.println("op.flatMap(v->\"新值新Optional\")的结果:" + op.flatMap(v->Optional.of("新值新Optional")));   //有值返新值新Optional, null值返empty(); 参数和map不一样. 逻辑一样
		out.println("op.or(()->Optional.of(\"新Optional包装的null替代品\")的结果:" + op.or(()->Optional.of("新Optional包装的null替代品")));   //有值返自己, null值返新Optional包装的null替代品; 

		
		
		
		hr("empty()");
		
		
		
		op = Optional.empty(); // 返回强制转换的 private static final Optional<?> EMPTY = new Optional<>(null);
		out.println("isEmpty()="+op.isEmpty());    //  isEmpty()  源码return value == null;
		out.println("isPresent="+op.isPresent());  //  isPresent()源码return value != null;
		try {
			Object o2 = op.get();  // 取值, 值空则抛throw new NoSuchElementException("No value present");
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("get()抛的"); }
		out.println(op.orElse("空指针默认值"));     //  orElse(    源码public T orElse(T other) {return value != null ? value : other;}
		out.println(op.orElseGet(()->{return "用Supplier实现的空指针默认值";}));
		out.println(op.orElseGet(()->"也可以省略return和分号大括号写成这样的:用Supplier实现的空指针默认值"));
		try {
			Object o2 = op.orElseThrow();  // 取值, 值空则抛throw new NoSuchElementException("No value present");
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		try {
			Object o2 = op.orElseThrow(()->new Exception("自定义异常"));  // 取值, 值空则抛自定义的异常;
			out.println(o2);
		}catch(Exception e) {e.printStackTrace(out); out.println("orElseThrow()抛的"); }
		op.ifPresent(v->{out.println("因为值不为null,所以执行了 ifPresent(Consumer<? super T> action) 值为:"+v);});  //如果不null就执行拉姆达
		op.ifPresentOrElse(
				v->{out.println("因为值不为null,所以ifPresentOrElse(执行了第一个参数的拉姆达,如同ifPresent方法,值为:"+v);}
				,
				new Thread(()->{out.println("看到这句说明值null, 如果null值则ifPresentOrElse执行第二个参数的Runnable, 因为新起线程,所以不会阻塞. "); })
				);
		out.println("op.filter(v->true) 的结果:" + op.filter(v->true));    //有值且真返自己, null值或假返empty();
		out.println("op.filter(v->false)的结果:" + op.filter(v->false));   //有值且真返自己, null值或假返empty();
		out.println("op.map(v->\"新值\")的结果:" + op.map(v->"新值"));   //有值返新值新Optional, null值返empty();  参数和flatMap不一样, 逻辑一样
		out.println("op.flatMap(v->\"新值新Optional\")的结果:" + op.flatMap(v->Optional.of("新值新Optional")));   //有值返新值新Optional, null值返empty(); 参数和map不一样. 逻辑一样
		out.println("op.or(()->Optional.of(\"新Optional包装的null替代品\")的结果:" + op.or(()->Optional.of("新Optional包装的null替代品")));   //有值返自己, null值返新Optional包装的null替代品; 

		
	}
	
	
	static void hr(String str) {		for(int c=0;c<100;c++)out.append("-"); out.append(str).println();	}
	static void hr() {hr("");}

}

其它参考

Optional的用法

Optional 是 Java 8 引入的一个容器对象,它可能包含也可能不包含非 null 的值。Optional 的主要目的是提供一个更好的替代方案,以避免 NullPointerException 和改进代码的可读性。

以下是 Optional 的一些基本用法:

  1. 创建 Optional 对象

使用 Optional.of()Optional.empty()Optional.ofNullable() 方法创建 Optional 对象。

java 复制代码
Optional<String> optional1 = Optional.of("value");  // 非null值
Optional<String> optional2 = Optional.empty();     // 空Optional
String possiblyNull = getPossiblyNullValue();
Optional<String> optional3 = Optional.ofNullable(possiblyNull);  // 可能是null或非null
  1. 检查值是否存在

使用 isPresent() 方法检查 Optional 对象是否包含值。

java 复制代码
if (optional.isPresent()) {
    // 值存在
} else {
    // 值不存在
}
  1. 获取值

使用 get() 方法获取 Optional 对象的值。如果值不存在,此方法将抛出 NoSuchElementException。因此,在调用 get() 之前,最好先检查值是否存在。

java 复制代码
if (optional.isPresent()) {
    String value = optional.get();
}
  1. 更安全的值获取

使用 orElse() 方法获取 Optional 对象的值,如果值不存在,则返回一个默认值。

java 复制代码
String value = optional.orElse("default");
  1. 执行操作

使用 ifPresent() 方法对 Optional 对象的值执行操作,如果值存在。

java 复制代码
optional.ifPresent(value -> System.out.println(value));
  1. 转换值

使用 map() 方法对 Optional 对象的值进行转换。如果值不存在,则不进行任何操作。

java 复制代码
Optional<Integer> lengthOptional = optional.map(String::length);
  1. 处理空值

使用 orElseGet() 方法在 Optional 对象为空时计算并返回一个值。这对于需要执行耗时操作以获取默认值的情况非常有用。

java 复制代码
String value = optional.orElseGet(() -> expensiveDefaultValueComputation());
  1. 抛出异常

使用 orElseThrow() 方法在 Optional 对象为空时抛出一个异常。你可以提供一个 Supplier<Throwable> 来创建并抛出所需的异常。

java 复制代码
String value = optional.orElseThrow(() -> new IllegalStateException("Value not present"));
  1. 过滤值

使用 filter() 方法根据特定条件过滤 Optional 对象的值。如果值存在且满足条件,返回包含该值的 Optional;否则返回空 Optional。

java 复制代码
Optional<String> filteredOptional = optional.filter(value -> "desiredValue".equals(value));
  1. 链式调用

你可以将多个 Optional 操作链接在一起,以创建更复杂的逻辑。例如:

java 复制代码
String result = optional
        .filter(value -> "desiredValue".equals(value))
        .map(String::toUpperCase)
        .orElse("DEFAULT");

Java Optional是Java 8引入的一个类,用于解决空指针异常的问题。它可以包含一个非空值,也可以为空。下面是Java Optional的常用用法:

  1. 创建Optional对象:
java 复制代码
Optional<String> optional = Optional.of("value"); // 创建一个包含非空值的Optional对象
Optional<String> emptyOptional = Optional.empty(); // 创建一个空的Optional对象
Optional<String> nullableOptional = Optional.ofNullable(null); // 创建一个可能为空的Optional对象
  1. 判断Optional对象是否包含值:
java 复制代码
optional.isPresent(); // 判断Optional对象是否包含非空值,返回true或false
  1. 获取Optional对象的值:
java 复制代码
optional.get(); // 获取Optional对象中的非空值,如果Optional对象为空,则抛出NoSuchElementException异常
optional.orElse("default"); // 获取Optional对象中的非空值,如果Optional对象为空,则返回默认值
optional.orElseGet(() -> "default"); // 获取Optional对象中的非空值,如果Optional对象为空,则通过Supplier函数式接口返回默认值
optional.orElseThrow(() -> new RuntimeException("Value not present")); // 获取Optional对象中的非空值,如果Optional对象为空,则抛出指定的异常
  1. 使用Optional对象的值进行操作:
java 复制代码
optional.ifPresent(value -> System.out.println(value)); // 如果Optional对象包含非空值,则执行指定的操作
optional.ifPresentOrElse(
    value -> System.out.println(value), 
    () -> System.out.println("Value not present")); // 如果Optional对象包含非空值,则执行指定的操作,否则执行默认的操作
  1. 使用Optional对象进行过滤:
java 复制代码
optional.filter(value -> value.length() > 5); // 如果Optional对象包含非空值,并且满足指定的条件,则返回包含该值的Optional对象,否则返回空的Optional对象
  1. 使用Optional对象进行映射:
java 复制代码
optional.map(value -> value.toUpperCase()); // 如果Optional对象包含非空值,则对该值进行映射操作,并返回包含映射结果的Optional对象,否则返回空的Optional对象
optional.flatMap(value -> Optional.of(value.toUpperCase())); // 如果Optional对象包含非空值,则对该值进行映射操作,并返回映射结果,否则返回空的Optional对象
相关推荐
Themberfue19 分钟前
Java 网络原理 ①-IO多路复用 || 自定义协议 || XML || JSON
xml·java·开发语言·网络·计算机网络·json
wm104324 分钟前
JavaEE 3大组件 Listener Servlet Filter
java·servlet·java-ee
卡戎-caryon1 小时前
【MySQL】01.MySQL环境安装
数据库·笔记·mysql·环境配置
疯一样的码农1 小时前
基于Spring Boot + Vue3实现的在线商品竞拍管理系统源码+文档
java·spring boot·后端
m0_748251352 小时前
【SpringBoot】日志文件
java·spring boot·spring
m0_748234712 小时前
Java-33 深入浅出 Spring - FactoryBean 和 BeanFactory BeanPostProcessor
java·开发语言·spring
菲力蒲LY2 小时前
刷新页面一次,错误地进行了多次重复调用后端服务
笔记
知初~2 小时前
java相关学习文档或网站整理
java·开发语言·学习
码农小灰2 小时前
什么是缓存穿透、缓存击穿、缓存雪崩,在项目中是如何解决和预防?它们分别会带来什么危害?
java·缓存
a栋栋栋2 小时前
apifox
java·前端·javascript