可选和对象:空指针救星!

没有人喜欢空指针异常 我们有办法摆脱它们吗?
也许 。



这篇文章中讨论了几种技术:

  • 可选类型(Java 8中的新增功能)
  • 对象类(旧的Java 7东西!)

Java 8中的可选类型

它是什么?

  • Java 8中引入的一种新类型(类)
  • 打算充当特定类型的对象或没有对象(空)的方案的“ 包装器

用简单的话来说,它是处理空值的更好替代品警告 :起初可能不是很明显!)

基本用法

它是一种类型(一个类)–那么,如何创建它的实例?

只需在Optional类中使用三个静态方法。

public static Optional<String> stringOptional(String input) {
    return Optional.of(input);
}

简单明了–创建一个包含值的Optional包装器。 当心–如果值本身为null,将抛出NPE!

public static Optional<String> stringNullableOptional(String input) {
	if (!new Random().nextBoolean()) {
		input = null;
	}
		
	return Optional.ofNullable(input);
}

我个人认为好一点。 这里没有NPE的风险–如果输入为空,则将返回空的 Optional。

public static Optional<String> emptyOptional() {
	return Optional.empty();
}

如果您要有目的地返回“空”值。 'empty'并不意味着null

好了–使用/使用Optional怎么样?

public static void consumingOptional() {
	Optional<String> wrapped = Optional.of("aString");
	if (wrapped.isPresent()) {
		System.out.println("Got string - " + wrapped.get());
	}
	else {
		System.out.println("Gotcha !");
	}
}

一种简单的方法是检查Optional包装器是否具有实际值(使用isPresent方法)–这将使您想知道它是否比使用if(myObj!= null)好 。 不用担心,我也会解释这一点。

public static void consumingNullableOptional() {
	String input = null;
	if (new Random().nextBoolean()) {
		input = "iCanBeNull";
	}
	Optional<String> wrapped = Optional.ofNullable(input);
	System.out.println(wrapped.orElse("default"));
}

如果包装的值为null,则可以使用orElse来返回默认值,这是显而易见的。 我们避免了在提取实际值之前调用ifPresent的明显冗长。

public static void consumingEmptyOptional() {
	String input = null;
	if (new Random().nextBoolean()) {
		input = "iCanBeNull";
	}
	Optional<String> wrapped = Optional.ofNullable(input);
	System.out.println(wrapped.orElseGet(
		() -> {
			return "defaultBySupplier";
		}

	));
}

我对此有些困惑。 为什么要使用两种单独的方法来实现相似的目标? orElseorElseGet很可能已被重载 (相同名称,不同参数)。

无论如何,这里唯一明显的区别是参数本身–您可以选择提供一个Lambda表达式来表示Supplier <T> (功能接口)的实例。

与常规的空值检查相比,使用Optional更好吗?

  • 总的来说,使用Optional的主要好处是能够清楚地表达您的意图 -简单地从方法中返回null会使消费者在怀疑是否故意的时候(当实际的NPE出现时)充满了疑惑。并且需要对Javadocs进行进一步的内省(如果有)。 借助Optional,其水晶般清晰
  • 有以下几种方式可以完全避免NPE与可选-在上面的例子中所提到的,使用Optional.ofNullable(可选创建过程中)和否则容易orElseGet(可选消费过程中)从NPE上保护我们一起

另一个救星!

(以防您无法使用Java 8)

查看此代码段。

package com.abhirockzz.wordpress.npesaviors;

import java.util.Map;
import java.util.Objects;

public class UsingObjects {

	String getVal(Map<String, String> aMap, String key) {
		return aMap.containsKey(key) ? aMap.get(key) : null;
	}

	public static void main(String[] args) {
		UsingObjects obj = new UsingObjects();
		obj.getVal(null, "dummy");
	}
}

什么可能为空?

  • 地图对象
  • 执行搜索所依据的密钥
  • 在其上调用方法的实例

在这种情况下抛出NPE时,我们永远无法确定什么是null

输入对象类

package com.abhirockzz.wordpress.npesaviors;

import java.util.Map;
import java.util.Objects;

public class UsingObjects {
	
	String getValSafe(Map<String, String> aMap, String key) {
		Map<String, String> safeMap = Objects.requireNonNull(aMap,
				"Map is null");
		String safeKey = Objects.requireNonNull(key, "Key is null");

		return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
	}

	public static void main(String[] args) {
		UsingObjects obj = new UsingObjects();
		obj.getValSafe(null, "dummy");
	}
}

requireNonNull方法:

  • 如果它不为空,则简单地返回值
  • 如果值为null,则将向NPE投掷指定的消息

为什么这比if(myObj!= null)更好

您将看到的堆栈跟踪将明显具有Objects.requireNonNull方法调用。 这以及您的自定义错误消息将帮助您更快地发现错误。 。 .IMO快得多!

您也可以编写用户定义的检查,例如,实施强制执行非空性的简单检查

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

public class RandomGist {

    public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
        Objects.requireNonNull(object);
        Objects.requireNonNull(predicate);
        if (predicate.test(object)){
            throw new IllegalArgumentException(msgToCaller);
        }
        return object;
    }

    public static void main(String[] args) {
        
    //Usage 1: an empty string (intentional)

    String s = "";
    System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "My String is Empty!"));

    //Usage 2: an empty List (intentional)
    List list =  Collections.emptyList();
    System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "List is Empty!").size());

    //Usage 3: an empty User (intentional)
    User user = new User("");
    System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "User is Empty!"));
}

    private static class User {
        private String name;

        public User(String name){
            this.name = name;
        }

        public String getName(){
            return name;
        }
    }
}

不要让NPE在错误的地方痛苦。 我们拥有一套不错的工具来更好地处理NPE或完全消除它们!

干杯!

翻译自: https://www.javacodegeeks.com/2014/09/optional-and-objects-null-pointer-saviours.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值