数字类 default 0和 default 0_04Optional类和接口中的default、static方法
这篇文章,介绍Jave8的 Optional 类和接口的 default、static 方法。
1、Optional类
Optional:Java8 java.util包中提供的一个可以包含或者不包含非null值的容器对象。
通过 Optional 我们不用显式进行空值检测 ( if( T == null ) )也很好的解决空指针异常
1.1 Optional API
Optional 方法 | 说明 |
---|---|
static Optional empty() | 返回一个空Optional(值为null) |
boolean equals(Object obj) | 指示给定的对象是否 equals 此Optional的value |
Optional filter(Predicate super predicate) | 如果 Optional 的值存在而且匹配给定的 predicate(断定型函数式接口),返回当前Optional,否则返回一个空Optional(值为null) |
Optional flatMap(Function super T,Optional> mapper) | 如果 Optional 的值存在,应用提供的映射方法并返回结果 Optional,否则返回一个空的Optional |
T get() | 如果此 Optional 存在值,则返回值,否则抛出NoSuchElementException |
int hashCode() | 返回当前值的哈希码值(如果有),如果没有值,则返回0。 |
void ifPresent(Consumer super T> consumer) | 如果存在值,对该值应用指定的 Consumer(消费型函数式接口),否则不执行任何操作。 |
boolean isPresent() | 如果存在值,返回true,否则返回false |
Optional map(Function super T,? extends U> mapper) | 如果值存在,对该值应用给定的映射方法,如果是非null的结果,返回一个描述该值的 optional,否则返回一个空Optional(值为null) |
static Optional of(T value) | 通过给定的value,返回一个值为给定value的Optional实例,value不能为null,若value为null,则抛出NullPointerException |
static Optional ofNullable(T value) | 通过给定的value,返回一个值为给定value的Optional实例,value可为null |
T orElse(T other) | 如果此Optional的value不为null,则返回value,否则返回给定的other对象 |
T orElseGet(Supplier extends T> other) | 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier(供给型函数式接口)返回一个T类型的对象 |
T orElseThrow(Supplier extends X> exceptionSupplier) | 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier创建一个Throwable |
String toString() | 返回非空字符串表示此Optional,适用于调试。 |
项目中常用的实例方法,用于解决空指针异常
isPresent()
方法,如果存在值,将返回true,否则返回false。orElse(T other)
方法,如果存在值,则返回当前Optional的value,否则返回 otherifPresent(Consumer super T> consumer)
,如果存在值,对该值应用指定的 Consumer,执行代码块,否则不做任何操作
1.2 Optional 源码
public final class Optional<T> {/** * empty()方法的公共实例 */private static final Optional> EMPTY = new Optional<>();
/** * Optional的值,类型为T */private final T value;
/** * 私有构造器 */private Optional() {this.value = null; }
/** * 返回一个空Optional(值为null) */public static Optionalempty() {@SuppressWarnings("unchecked") Optional t = (Optional) EMPTY;return t; }/** * value为入参的构造器,value不能为null,若value为null,则抛出NullPointerException */private Optional(T value) {this.value = Objects.requireNonNull(value); }/** * 通过给定的value,返回一个值为给定value的Optional实例,value不能为null,若value为null,则抛出NullPointerException */public static Optionalof(T value) {return new Optional<>(value); }/** * 通过给定的value,返回一个值为给定value的Optional实例,value可为null,若value为null,则返回 EMPTY */public static OptionalofNullable(T value) {return value == null ? empty() : of(value); }/** * 如果此 Optional 存在值,则返回值,否则抛出NoSuchElementException */public T get() {if (value == null) {throw new NoSuchElementException("No value present"); }return value; }/** * 如果存在值 value!=null,返回true,否则返回false */public boolean isPresent() {return value != null; }/** * 如果存在值,对该值应用指定的 Consumer(消费型函数式接口),否则不执行任何操作。 */public void ifPresent(Consumer super T> consumer) {if (value != null) consumer.accept(value); }/** * 如果 Optional 的值存在而且匹配给定的 predicate(断定型函数式接口),返回当前Optional,否则返回一个空Optional(值为null) */public Optionalfilter(Predicate super T> predicate) { Objects.requireNonNull(predicate);if (!isPresent())return this;elsereturn predicate.test(value) ? this : empty(); }/** * 如果值存在,对该值应用给定的映射方法,如果是非null的结果,返回一个描述该值的 optional,否则返回一个空Optional(值为null) */publicOptional map(Function super T, ? extends U> mapper) { Objects.requireNonNull(mapper);if (!isPresent())return empty();else {return Optional.ofNullable(mapper.apply(value)); } }/** * 如果 Optional 的值存在,应用提供的映射方法并返回结果Optional,否则返回一个空的Optional */publicOptional flatMap(Function super T, Optional> mapper) { Objects.requireNonNull(mapper);if (!isPresent())return empty();else {return Objects.requireNonNull(mapper.apply(value)); } }/** * 如果此Optional的value不为null,则返回value,否则返回给定的other对象 */public T orElse(T other) {return value != null ? value : other; }/** * 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier(供给型函数式接口)返回一个T类型的对象 */public T orElseGet(Supplier extends T> other) {return value != null ? value : other.get(); }/** * 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier创建一个Throwable */public T orElseThrow(Supplier extends X> exceptionSupplier) throws X {if (value != null) {return value; } else {throw exceptionSupplier.get(); } }/** * 指示给定的对象是否 equals 此Optional的value */@Overridepublic boolean equals(Object obj) {if (this == obj) {return true; }if (!(obj instanceof Optional)) {return false; } Optional> other = (Optional>) obj;return Objects.equals(value, other.value); }/** * 返回当前值的哈希码值(如果有),如果没有值,则返回0。 */@Overridepublic int hashCode() {return Objects.hashCode(value); }/** * 返回非空字符串表示此Optional,适用于调试。 */@Overridepublic String toString() {return value != null ? String.format("Optional[%s]", value) : "Optional.empty"; }}
1.3 Optional 简单使用
public class Person {
//姓名private String name;//年龄private long age;
public Person(String name, long age) {this.name = name;this.age = age; }
public String getName() {return name; }
public void setName(String name) {this.name = name; }
public long getAge() {return age; }
public void setAge(long age) {this.age = age; }
@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}'; }
}
@Testpublic void test() { Person p = new Person("张三", 18);
// 通过给定的value,返回一个值为给定value的Optional实例,若value为null,则抛出NullPointerException// Optional o = Optional.of(null); Optional opPerson = Optional.of(p); System.out.println("of(T value): " + opPerson);// 通过给定的value,返回一个值为给定value的Optional实例,value可为null,若value为null,则返回 Optional.EMPTY Optional opNull = Optional.ofNullable(null); System.out.println("ofNullable(T value): " + opNull);// 如果此 Optional 存在值,则返回值,否则抛出NoSuchElementException// Person person = opNull.get();// 抛出NoSuchElementException Person person = opPerson.get(); System.out.println("T get(): " + person);// 如果存在值 value!=null,返回true,否则返回falseboolean opNullPresent = opNull.isPresent(); System.out.println("opNull persent: " + opNullPresent);if (!opNull.isPresent()) { System.out.println("opNull 的 value == null"); } else { System.out.println("opNull 的 value = " + opNull.get()); }boolean opPersonPresent = opPerson.isPresent(); System.out.println("opPerson persent: " + opPersonPresent);// 如果 opPerson 的 value != null,输出下面语句 opPerson.ifPresent(value -> System.out.println(value.getName() + "的年龄是" + value.getAge()));// 如果 Optional 的值存在而且匹配给定的 predicate(断定型函数式接口),返回当前Optional,否则返回一个空Optional(值为null) System.out.println("opNull.filter(): " + opNull.filter(value -> value.getAge() == 18)); System.out.println("opPerson.filter() 匹配age==18: " + opPerson.filter(value -> value.getAge() == 18)); System.out.println("opPerson.filter() 匹配age==19: " + opPerson.filter(value -> value.getAge() == 19));// 如果值存在,对该值应用给定的映射方法,如果是非null的结果,返回一个描述该值的 optional,否则返回一个空Optional(值为null)// Person::getName 方法引用等同于 lambda表达式:value->value.getName()// Function funcGetName = value->value.getName(); Function funcGetName = Person::getName; Optional opNameofOpNull = opNull.map(funcGetName); Optional opNameofOpPerson = opPerson.map(funcGetName); System.out.println("opNull.map(): " + opNameofOpNull); System.out.println("opPerson.map(): " + opNameofOpPerson);// 如果 Optional 的值存在,应用提供的映射方法并返回结果 Optional,否则返回一个空的Optional Optional op1 = opNull.flatMap(value -> Optional.of(new Person("李四", 20))); Optional op2 = opPerson.flatMap(value -> Optional.of(new Person("李四", 20))); System.out.println("opNull.flatMap(): " + op1); System.out.println("opPerson.flatMap(): " + op2);// 如果此Optional的value不为null,则返回value,否则返回给定的other对象 Person wangwu = new Person("王五", 25); System.out.println("opNull.orElse(): " + opNull.orElse(wangwu)); System.out.println("opPerson.orElse(): " + opPerson.orElse(wangwu));// 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier(供给型函数式接口)返回一个T类型的对象 Supplier supplier = () -> new Person("赵六", 26); System.out.println("opNull.orElseGet(): " + opNull.orElseGet(supplier)); System.out.println("opPerson.orElseGet(): " + opPerson.orElseGet(supplier));// 如果此Optional的value不为null,则返回value,否则通过调用给定的Supplier创建一个Throwable Supplier nullPointerExceptionSupplier = () -> new NullPointerException("value is null"); System.out.println("opPerson.orElseThrow(): " + opPerson.orElseThrow(nullPointerExceptionSupplier)); System.out.println("opNull.orElseThrow(): " + opNull.orElseThrow(nullPointerExceptionSupplier)); }
运行结果:
of(T value): Optional[Person{name='张三', age=18}]ofNullable(T value): Optional.emptyT get(): Person{name='张三', age=18}opNull persent: falseopNull 的 value == nullopPerson persent: true张三的年龄是18opNull.filter(): Optional.emptyopPerson.filter() 匹配age==18: Optional[Person{name='张三', age=18}]opPerson.filter() 匹配age==19: Optional.emptyopNull.map(): Optional.emptyopPerson.map(): Optional[张三]opNull.flatMap(): Optional.emptyopPerson.flatMap(): Optional[Person{name='李四', age=20}]opNull.orElse(): Person{name='王五', age=25}opPerson.orElse(): Person{name='张三', age=18}opNull.orElseGet(): Person{name='赵六', age=26}opPerson.orElseGet(): Person{name='张三', age=18}opPerson.orElseThrow(): Person{name='张三', age=18}
java.lang.NullPointerException: value is null
at com.xander.java8._optional.OptionalTest.lambda$test$7(OptionalTest.java:83) at java.util.Optional.orElseThrow(Optional.java:290)...
2 接口的增强:default 和 static 方法
2.1 default方法
java8中允许接口中包含具有具体实现的方法,用
default
关键字修饰,这类型方法称为“默认方法”。
不用被default
关键字吓到,default
方法也是普通方法,只不过它遵循"类优先"
原则(下面介绍)
我们看JDK源码时,可以经常看到 default 方法,如 Consumer类
:
@FunctionalInterfacepublic interface Consumer<T> {
/** * Performs this operation on the given argument. * * @param t the input argument */void accept(T t);
/** * 这就是一个default方法 */default ConsumerandThen(Consumer super T> after) { Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); }; }}
default方法的调用遵循
"类优先"
原则
接口中定义了default方法,如果实现类中重写了该方法,则调用的是实现类中重写后的方法,如果实现类中没有重写default方法,则执行的是接口中定义的default方法。
如果实现类实现了一个接口和继承了一个父类,接口的默认方法和父类中某一个方法具有相同名称和参数列表,而且实现类没有进行该方法的重写,则使用的是父类的方法。
方法冲突,实现类中实现了两个接口,这两个接口中具有相同名称和参数列表的方法(不管是不是default方法),如果实现类中没有对default方法进行重写,则编译出错。实现类中必须必须重写覆盖该方法来解决冲突。
2.2 default方法简单使用
public interface DefaultIntf {
/** * default 方法 */default void sayHello() { System.out.println("DefaultIntf say hello 2 you"); }}
public interface SayHelloIntf {/** * default 方法 */default void sayHello() { System.out.println("SayHelloIntf hello"); }}
public class Animal {
public void sayHello() { System.out.println("Animal say hello"); }}
public class Cat implements DefaultIntf {
@Overridepublic void sayHello() { System.out.println("Hello I am Cat sayHello"); }
}
public class Dog implements DefaultIntf {}
public class Bird extends Animal implements DefaultIntf {}
public class Fish implements SayHelloIntf, DefaultIntf {
/** * **方法冲突**,类中实现了两个接口,这两个接口中具有相同名称和参数列表的方法(不管是不是default方法), * 如类中没有对default方法进行重写,则编译出错。子类中必须必须覆盖该方法来解决冲突。 */@Overridepublic void sayHello() { System.out.println("Hello this is Fish"); }}
@Testpublic void testDefaultMethod() { DefaultIntf dog = new Dog(); DefaultIntf cat = new Cat(); Bird bird = new Bird(); Fish fish = new Fish();
// 执行默认方法// 实现类中没有重写default方法,执行的是接口中的default dog.sayHello();// 实现类中对default进行重写,则执行的是重写后的方法 cat.sayHello();// 如果类实现了一个接口和继承了一个父类,接口的默认方法和父类中某一个方法具有相同名称和参数列表,而且子类没有进行该方法的重写,则使用的是父类的方法。 bird.sayHello();// 类中实现了两个接口,这两个接口中具有相同名称和参数列表的方法(不管是不是default方法),子类中必须必须覆盖该方法,否则编译异常。 fish.sayHello(); }
运行结果:
DefaultIntf say hello 2 youHello I am Cat sayHelloAnimal say helloHello this is Fish
2.3 项目实战场景
获取接口实例的泛型Class
/** * Description: 接口:包含一个default方法,该接口所有的实例都可以通过该default获取泛型类型 * * @author Xander * datetime: 2020/9/7 */public interface GenericIntf<T> {
/** * 默认方法:获取泛型T的 Class * * @return */default ClassgetGenericClass() { Type[] types = this.getClass().getGenericInterfaces(); ParameterizedType parameterizedType = (ParameterizedType) types[0]; Class tClass = (Class) parameterizedType.getActualTypeArguments()[0];return tClass; }}/** * Description: GenericIntf的实现类,泛型类型是Double * * @author Xander * datetime: 2020/9/7 */public class GenericDouble implements GenericIntf<Double> {}/** * Description: GenericIntf的实现类,泛型类型是Integer * * @author Xander * datetime: 2020/9/7 */public class GenericInteger implements GenericIntf<Integer> {}@Testpublic void testGeneric() {// 获取 GenericIntf接口实例的 泛型类型 GenericIntf genericInt = new GenericInteger(); GenericIntf genericDouble = new GenericDouble(); Class genericIntClass = genericInt.getGenericClass();//泛型类型是 Integer Class genericDoubleClass = genericDouble.getGenericClass();//泛型类型是 Double System.out.println("GenericInteger的泛型类型:" + genericIntClass); System.out.println("genericDouble的泛型类型:" + genericDoubleClass); }
运行结果:
GenericInteger 的泛型类型:class java.lang.IntegerGenericDouble 的泛型类型:class java.lang.Double
2.4 static 方法简单使用
java8允许接口像普通类一样定义和使用静态方法。
public interface StaticIntf {
static void printInfo() { System.out.println("执行接口中的static方法:" + StaticIntf.class); }}
@Testpublic void test(){// 执行接口中 static 方法 StaticIntf.printInfo(); }
运行结果:
执行接口中的static方法:interface com.xander.java8._06default_static_method.StaticIntf
结语: Optional类和接口的default、static可以作为很好的编程手段用来实现业务逻辑,Optional可以优雅地解决空指针异常,而接口的default和static方法,能够让我们定义在接口层级公共的方法,希望Java8的这两个特性能够帮助到大家。
代码:
https://github.com/wengxingxia/001java8.git
[慕课手记同步:04-Optional类和接口中的default、static方法] https://www.imooc.com/article/310370
提示: 根据相关法律法规和平台规则要求,自2018年2月12日起,新注册的微信公众帐号无法再开通留言功能。
有问题或希望交流的朋友,可以到 [慕课手记同步:04-Optional类和接口中的default、static方法] https://www.imooc.com/article/310370 下评论留言,一起学习进步。
欢迎关注公众号"黑桃"
数字类 default 0和 default 0_04Optional类和接口中的default、static方法相关推荐
- Java基础知识(二)(Object类的常用方法、日期时间类、System类、StringBuilder类、包装类、Collection集合、Iterator迭代器、泛型、list集Set接口...)
文章目录 Java基础知识(二) 1.Object类的常用方法 1.1 toString方法 1.2 equals方法 1.3 Objects类 2.日期时间类 2.1 Date类 2.2 DateF ...
- 北京某高校可用的电话号码有以下几类,校内电话号码由4位数字组成,第1位数字不是0,校外电话又分为本市电话和外地电话两类,拨校外电话需先拨0,若是本市电话则再接着拨8位数字(第1位不是0)
题目介绍 北京某高校可用的电话号码有以下几类: 校内电话号码由4位数字组成,第1位数字不是0: 校外电话又分为本市电话和外地电话两类,拨校外电话需先拨0, 若是本市电话则再接着拨8位数字(第1位不是0 ...
- java 数字翻译成英文_Java实现将数字日期翻译成英文单词的工具类实例
本文实例讲述了Java实现将数字日期翻译成英文单词的工具类.分享给大家供大家参考,具体如下: package com.sunyard.etp.ag.util; import java.math.Big ...
- java 数字翻译成英文_Java实现数字日期翻译成英文单词的工具类案例分享
这篇文章主要介绍了Java实现将数字日期翻译成英文单词的工具类,结合完整实例形式分析了Java日期转换与字符串操作相关实现技巧,需要的朋友可以参考下 本文实例讲述了Java实现将数字日期翻译成英文单词 ...
- C# 语言规范_版本5.0 (第10章 类)
1. 类 类是一种数据结构,它可以包含数据成员(常量和字段).函数成员(方法.属性.事件.索引器.运算符.实例构造函数.静态构造函数和析构函数)以及嵌套类型.类类型支持继承,继承是一种机制,它使派生类 ...
- 设计模式(0):UML类图(Class Diagram)
文章目录 一. 基本概念 1. 泛化(Generalization) 2. 实现(Realization) 3. 关联(Association) 4. 聚合(Aggregation) 5. 组合(Co ...
- 数字基带部分响应matlab,第Ⅰ类部分响应系统的抗噪声性能分析与仿真
第Ⅰ类部分响应系统的抗噪声性能分析与仿真 陈海英 (漳州师范学院物理与电子信息工程系,福建 漳州363000) 摘要:分析了第Ⅰ类部分响应系统的抗噪声性能,并利用MATLAB软件仿真计算不同信噪比下的 ...
- ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件!
在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能 ...
- ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件
在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能 ...
最新文章
- RuntimeWarning:Glyph 21435 missing from current font.
- python【洛谷算法题单-搜索】P1605 迷宫
- matplotlib 显示批量图片_chapter4-1 简单数据可视化包Matplotlib整理1
- 【Jmeter】压力测试工具 Jmeter 使用
- 数学课本上的几大变态之处
- 【dfs】栅栏的木料(2012特长生 T4)
- 虚拟机安装mac os x实战
- 如何让大数据分析更有效
- 类数组变量定义与初始化
- e480win7显卡驱动_win7系统联想e480安装的操作方法
- 每日新闻丨阿里巴巴香港IPO指引价每股176港元左右;全球超级计算机500强榜单出炉...
- C++QT13位时间戳转换成年月日时分秒毫秒
- Java添加一个滑动验证码,有啥可难的,分分钟加一个
- css如何设置背景颜色透明?css设置背景颜色透明度的两种方法介绍
- 宝塔面板网站一打开cpu百分百_解决宝塔面板CPU占满100%,负载100%网站缓慢等问题(完全篇)...
- Wav音频文件剪切指定片段(限PCM格式)
- NLP - 微信好友个性签名情感分析( 基于Python开源库snownlp )
- openwrt - 性能监控 netdata
- revit开发__电缆桥接截面分布
- Vislight光源
热门文章
- [家里蹲大学数学杂志]第387期一套实变函数期末试题参考解答
- Android基础之用Eclipse搭建Android开发环境和创建第一个Android项目(Windows平台)...
- 飞鸽传书从微软官网上了解到微软正在推动虚拟化
- 做 局域网聊天 的人越来越多了
- 助力飞鸽传书高效沟通
- Facebook的规模还在继续扩大
- 『飞鸽』彻底学通string.Format以及IFormattable,IFormatProvider,ICustomFormatter
- Dell Caps Lock 切换大小写被窃取焦点问题解决办法
- 商业智能常见名词浅释(转载)
- 现在的编程语言越来越多,为什么 C 和 C++ 还没有被现在的时代淘汰呢?