登陆

Java8新特性:Optional类的正确运用姿态

admin 2019-08-23 295人围观 ,发现0个评论

空指针反常是咱们在实践开发中经常会遇到的问题,为了避免程序由于反常而中止,一般要在代码中增加很多的非空验证,例如一个开释 JDBC 相关资源的代码,如下所示。

public static void release(Connection conn,Statement stmt,ResultSet rs) {
try {
if(conn != null) {
conn.close();
}
if(stmt != null) {
stmt.close();
}
if(rs != null) {
rs.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

上述代码中的非空验证并没有多少技术含量,一起会使代码显得臃肿不胜,为了处理这类问题,Java8 引进了 Optional 类,Optional 便是一个容器,它能够保存恣意数据类型的值,包括 null,开发者无需进行空值检测,Optional 类的引进很好的处理了实践开发中的空指针反常问题,接下来咱们来详细学习 Optional 类的运用。

Optional 常用办法

1、empty(),回来一个空的 Optional 目标,界说如下所示。

public static Optional empty() {
@SuppressWarnings("unJava8新特性:Optional类的正确运用姿态checked")
Optional t = (Optional) EMPTY;
return t;
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.empty();
System.out.println(optional);
}
}

运转成果如下图所示。

2、of(T value),依据传入的 value 创立一个 Optional 目标,界说如下所示。

public static  Optional of(T value) {
return new Optional<>(value);
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.of("Hello World");
System.out.println(optional);
}
}

运转成果如下图所示。

能够看到输出的成果是 Optional[Hello World],假如要取出 Hello World 直接调用 get 办法即可,如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.of("Hello World");
System.out.println(optional.get());
}
}

可是需求留意的是,of 办法不能传 null,不然会抛出空指针反常,如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.of(null);
System.out.println(optional);
}
}


3、ofNullable(T value),和 of(T value) 办法相似,都是用来创立 Optional 目标的,差异在于 ofNullable(T value) 办法能够传 null,界说如下所示。

public static  Optional ofNullable(T value) {
return value == null ? empty() : of(value);
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(null);
System.out.println(optional);
}
}

运转成果如下图所示。


4、get(),回来 Optional 中存储的恣意类型值,假如 Optional 中的值为 null,则抛出 java.util.NoSuchElementException,界说如下所示。

public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable("Hello World");
System.out.println(optional.get());
optional = Optional.ofNullable(100);
System.out.println(optional.get());
Integer[] array = {1,2,3,4,5,6};
optional = Optional.ofNuJava8新特性:Optional类的正确运用姿态llable(array);
System.out.println(optional.get());
}
}

运转成果如下图所示。

假如是下面这种状况,直接抛出 java.util.NoSuchElementException 反常。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(null);
System.out.println(optional.get());
}
}

5、isPresent(),判别 Optional 存储的值是否存在,回来 true 表明有值,false 表明值不存在,界说如下所示。

public boolean isPresent() {
return value != null;
}

详细运用如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable("Hello World");
System.out.println(optional.isPresent());
optional = Optional.ofNullable(null);
System.out.println(optional.isPresent());
}
}

运转成果如下图所示。


6、ifPresent(Consumer consumer),假如值存在,履行 Consumer 的详细操作,假如值不存在,不做任何操作,界说如下所示。

public void ifPresent(Consumer action) {
if (value != null) {
action.accept(value);
}
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
//值存在
List list = Arrays.asList(1,2,3,4,5,6);
Optional optional = Optional.ofNullable(list);
System.out.print("值存在:");
optional.ifPresent(System.out::println);
//值不存在
optional = Optional.ofNullable(null);
System.out.print("值不存在:");
optional.ifPresent((str)-> System.out.println(str));
}
}


运转成果如下图所示。

7、ifPresentOrElse(Consumer action, Runnable emptyAction),假如值存在,履行 Consumer 的详细操作,假如值不存在,履行 emptyAction 的详细操作,界说如下所示。

public void ifPresentOrElse(Consumer action, Runnable emptyAction) {
if (value != null) {
action.accept(value);
} else {
emptyAction.run();
}
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
//值存在
List list = Arrays.asList(1,2,3,4,5,6);
Optional optional = Optional.ofNullable(list);
System.out.print("值存在:");
optional.ifPresentOrElse(System.out::println,()-> System.out.println("value is null"));
//值不存在
optional = Optional.ofNullable(null);
System.out.print("值不存在:");
optional.ifPresentOrElse(System.out::println,()-> System.out.println("value is null"));
}
}

运转成果如下图所示。


8、filter(Predicate predicate),依据传入的 Predicate 对 Optional 中的值进行过滤,满意条件则回来该 Optional 目标,不然回来一个空的 Optional,界说如下所示。

public Optional filter(Predicate predicate) {
Objects.requireNonNull(predicate);
if (!isPresent()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(1);
Predicate predicate = num -> num >= 3;
System.out.println(optional.filter(predicate));
predicate = num -> num < 3;
System.out.println(optional.filter(predicate));
}
}

运转成果如下图所示。

9、map(Function mapper),假如 Optional 有值,则履行 mapper 映射函数,并获取其回来值,假如回来值不为 null,则回来一个包括回来值的 Optional 目标,不然回来一个空的 Optional 目标,界说如下所示。

public  Optional map(Function mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return小米note2 empty();
} else {
return Optional.ofNullable(mapper.apply(value));
}
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
ClassB classB = new ClassB();
ClassA classA = new ClassA();
classA.setClassB(classB);
Optional optional = Optional.ofNullable(classA)
.map((classA1)->classA1.getClassB());
System.out.println(optional);
}
}
class ClassA {
private ClassB classB;
public ClassB getClassB() {
return classB;
}
public void setClassB(ClassB classB) {
this.classB = classB;
}
}
class ClassB {
}

上述代码表明假如 classA 中包括 classB,则直接回来一个 Optional[ClassB] 目标,不然回来一个空的 Optional 目标,运转成果如下图所示。


对上述代码进行修正,删去 classA.setClassB(classB); 如下所示。

ClassB classB = new ClassB();
ClassA classA = new ClassA();
Optional optional = Optional.ofNullable(classA)
.map((classA1)->classA1.getClassB());
System.out.println(optional);

运转成果如下图所示。


这儿需求留意的是 map 办法的调用有必要和 Optional 的创立连起来写,如下所示。

Optional optional = Optional.ofNullable(classA).map((classA1)->classA1.getClassB());

不能分隔写,过错写法如下所示。

Optional optional = Optional.ofNullable(classA);
optional.map((classA1)->classA1.getClassB());

10、flatMap(Function> mapper),功能与 map 相似,差异在于 map 的 mapper 映射函数可回来恣意数据类型,可是 flatMap 的 mapper 映射函数只能回来 Optional 类型,界说如下所示。

public  Optional flatMap(Function> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
@SuppressWarnings("unchecked")
Optional r = (Optional) mapper.apply(value);
return Objects.requireNonNull(r);
}
}

详细操作如下所示。

public class Java8新特性:Optional类的正确运用姿态Test {
public static void main(String[] args) {
ClassB classB = new ClassB();
ClassA classA = new ClassA();
classA.setClassB(classB);
Optional optional = Optional.ofNullable(classA)
.flatMap((classA1)->{
return Optional.ofNullable(classA1.getClassB());
});
System.out.println(optional);
}
}

运转成果如下图所示。


11、orElse(T other),假如 Optional 的值存在则回来,不然回来 other,界说如下所示。

public T orElse(T other) {
return value != null ? value : other;
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(1);
System.out.println(optional.orElse("value is null"));
optional = Optional.ofNullable(null);
System.out.println(optional.orElse("value is null"));
}
}

运转成果如下图所示。



12、orElseGet(Supplier supplier),功能与 orElse 相似,差异在于 orElse 可直接回来某个值,orElseGet 需求履行 supplier,并回来其成果,多了一个过程,界说如下所示。

public T orElseGet(Supplier supplier) {
return value != null ? value : supplier.get();
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(1);
System.out.println(optional.orElseGet(()->"value is null"));
optional = Optional.ofNullable(null);
System.out.println(optional.orElseGet(()->"value is null"));
}
}

运转成果如下图所示。



13、orElseThrow(),假如值存在则回来,不然抛出 NoSuchElementException,界说如下所示。

public T orElseThrow() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(1);
System.out.println(optional.orElseThrow());
optional = Optional.ofNullable(null);
System.out.println(optional.orElseThrow());
}
}

运转成果如下图所示。


14、orElseThrow(Supplier exceptionSupplier),功能与 orElseThrow 相似,假如值存在则回来,不然抛出 exceptionSupplier 回来的反常,界说如下所示。

public  T orElseThrow(Supplier exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}

详细操作如下所示。

public class Test {
public static void main(String[] args) {
Optional optional = Optional.ofNullable(1);
try {
System.out.println(optional.orElseThrow(()->{throw new IllegalStateException();}));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
optional = Optional.ofNullable(null);
try {
System.out.println(optional.orElseThrow(()->{throw new IllegalStateException();}));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}

运转成果如下图所示。


上面详细介绍了 Optional 类的各种办法,接下来咱们结合实践事例,来看看实践开发中运用 Optional 的优势。

实践事例

咱们来设置一个客户订单查询场景。

1、界说 3 个类 Consumer、Order、Product,其间 Consumer 包括 Order,Order 包括 Product,详细代码如下所示。

public class Consumer {
private Order order;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
public class Order {
private Product product;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
public class Product {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

2、别离创立 Consumer、Order、Product 目标,并完结级联,然后界说回来 Consumer 中 ProductName 的办法,传统的开发方式需求对涉及到的目标都进行非空验证,如下所示。

public class Test {
public static void main(String[] args) {
Product product = new Product();
product.setName("电脑");
Order order = new Order();
order.setProduct(product);
Consumer consumer = new Consumer();
consumer.setOrder(order);
System.out.println(getProductName(consumer));
}
public static String getProductName(Consumer consumer){
if(conJava8新特性:Optional类的正确运用姿态sumer != null){
Order order = consumer.getOrder();
if(order != null){
Product product = order.getProduct();
if(product != null){
return product.getName();
}
}
}
return null;
}
}

3、运用 Optional 类对上述代码进行修正,能够将代码变得愈加简练、高雅,不需求一层一层的写非空判别,可直接完结链式调用,如下所示。

public static String getProductName(Consumer consumer){
return Optional.ofNullable(consumer)
.map(consumer1 -> consumer1.getOrder())
.map(order -> order.getProduct())
.map(product -> product.getName())
.orElse(null);
}

4、运转成果如下图所示。


重视微信大众号「Java大联盟」,重视即可获取海量学习干货,一起还有不定期送书,键盘,鼠标等粉丝福利。

赶快来重视一波,海量资源拿到手软。

请关注微信公众号
微信二维码
Powered By Z-BlogPHP