java非空检查工具类Objects,Optional

一、Objects

JDK7里面新增的Objects类,本类由一些操作对象的静态工具方法构成,这些工具方法包括了非空检查、方法的非空参数检查、 比较对象的hashCode、为对象返回一个字符串表示、比较两个对象等。 本文是以java8版本介绍Objects类

1、判断对象是否为null
//判断一个对象是否为空,如果为空返回true
static boolean isNull(Object obj);
            
//判断一个对象是否为空,如果不为空返回true
static boolean nonNull(Object obj);            
2、空指针判断处理
//对象不能为空,否则抛出NullPointerException
static <T> T requireNonNull(Tob j);
//对象不能为空,否则抛出NullPointerException,message是异常信息说明
static<T> T requireNonNull(Tobj,String message)static <T> T requireNonNull(T obj,Supplier<String> messageSupplier)
3、hashCode
// return o!=null? o.hashCode():0;
static int hashCode(Object o);

// return Arrays.hashCode(values);
static int hash(Object...values)
4、equals
// return(a==b)||(a!=null&&a.equals(b));
static boolean equals(Objecta,Objectb)

//判断2个数组对象是否相等,这个方法进行了非空判断
//if(a==b)
//return true;
//else if(a==null||b==null)
//return false;
//else
//return Arrays.deepEquals0(a,b);
static boolean deepEquals(Object a,Object b)
4、toString
//return String.valueOf(o);
static String toString(Objecto)

//return(o!=null)? o.toString():nullDefault;
static String toString(Objecto,String nullDefault)
5、compare
///return(a==b)?0:c.compare(a,b);
static<T> int compare(Ta,Tb,Comparator<? super T> c)

二、Optional

Java中还有OptionalInt OptionalLong,OptionalDouble其方法和Optional差不多,这里就不介绍了

1、创建 Optional 实例
static <T> Optional<T>  empty() 

static <T> Optional<T>  of(T value)

static <T> Optional<T>  ofNullable(T value)

你可以使用 of() 和 ofNullable() 方法创建包含值的 Optional。两个方法的不同之处在于如果你把 null 值作为参数传递进去

of() 方法会抛出 NullPointerException:

你看,我们并没有完全摆脱 NullPointerException。因此,你应该明确对象不为 null 的时候使用 of()。

如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法

2、返回值
public T get()//如果值为null,抛出 NoSuchElementException 。

public T orElse(T other)

public T orElseGet(Supplier<? extends T> other)

Optional 类提供了 API 用以返回对象值,或者在对象为空的时候返回默认值。
这里你可以使用的第一个方法是 orElse(),它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:

@Test
public void whenEmptyValue_thenReturnDefault() {
    User user = null;
    User user2 = new User("anna@gmail.com", "1234");
    User result = Optional.ofNullable(user).orElse(user2);	   
}

这里 user 对象是空的,所以返回了作为默认值的 user2。
如果对象的初始值不是 null,那么默认值会被忽略:

第二个同类型的 API 是 orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应) 函数式接口,并将返回其执行结果:

User result = Optional.ofNullable(user).orElseGet( () -> user2);

orElse() 和 orElseGet() 的不同之处

乍一看,这两种方法似乎起着同样的作用。然而事实并非如此。我们创建一些示例来突出二者行为上的异同。

我们先来看看对象为空时他们的行为:

public void givenEmptyValue_whenCompare_thenOk() {
    User user = null
    logger.debug("Using orElse");
    User result = Optional.ofNullable(user).orElse(createNewUser());
    logger.debug("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}

private User createNewUser() {
    logger.debug("Creating New User");
    return new User("extra@gmail.com", "1234");
}

上面的代码中,两种方法都调用了 createNewUser() 方法,这个方法会记录一个消息并返回 User 对象。
代码输出如下:

Using orElse
Creating New User
Using orElseGet
Creating New User

由此可见,当对象为空而返回默认对象时,行为并无差异。

我们接下来看一个类似的示例,但这里 Optional 不为空:

@Test
public void givenPresentValue_whenCompare_thenOk() {
    User user = new User("john@gmail.com", "1234");
    logger.info("Using orElse");
    User result = Optional.ofNullable(user).orElse(createNewUser());
    logger.info("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}
这次的输出:
Using orElse
Creating New User
Using orElseGet

这个示例中,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。
在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

为什么呢?其源码如下

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

  
public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
}

按理说当value不等于null时,不会到else模块啊,那么为什么还会执行createNewUser()方法?

因为你是将方法作为一个实参传入方法,所以 执行orElse(createNewUser());等于 String other = createNewUser();orElse(other );

因此会执行createNewUser()方法。

证明

public static void main(String[] args)throws IOException{

        orElse("1",get());//执行了方法
}
public static String get(){
        System.out.println("执行了方法");
        return "";

}
public static Object orElse(String value,String str){
        return value;
}
3、返回异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)throws X

除了 orElse() 和 orElseGet() 方法,Optional 还定义了 orElseThrow() API —— 它会在对象为空的时候抛出异常,而不是返回备选的值:

public void  whenThrowException_thenOk() {
    User result = Optional.ofNullable(user).orElseThrow( () -> new IllegalArgumentException());
}

这里,如果 user 值为 null,会抛出 IllegalArgumentException。
个方法让我们有更丰富的语义,可以决定抛出什么样的异常,而不总是抛出 NullPointerException。
现在我们已经很好地理解了如何使用 Optional,我们来看看其它可以对 Optional 值进行转换和过滤的方法。

4、转换值

有很多种方法可以转换 Optional 的值。我们从 map() 和 flatMap() 方法开始。

public <U> Optional<U> map(Function<? super T,? extends U> mapper)
public <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

先来看一个使用 map() API 的例子:

	@Test
public void  whenMap_thenOk() {
    User user = new User("anna@gmail.com", "1234");
    String email = Optional.ofNullable(user) .map(u -> u.getEmail()).orElse("default@gmail.com");
	    assertEquals(email, user.getEmail());
}

map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可
能 —— 这里的下一环就是 orElse()。

相比这下,flatMap() 也需要函数作为参数,并对值调用这个函数,然后直接返回结果。
下面的操作中,我们给 User 类添加了一个方法,用来返回 Optional:

	public class User {    
    private String position;
	    public Optional<String>  getPosition() {
        return Optional.ofNullable(position);
    }
	    //...
}

既然 getter 方法返回 String 值的 Optional,你可以在对 User 的 Optional 对象调用 flatMap() 时,用它作为参数。其返回的值是解除包装的 String 值:

@Test
public void  whenFlatMap_thenOk() {
    User user = new User("anna@gmail.com", "1234");
    user.setPosition("Developer");
    String position = Optional.ofNullable(user) .flatMap(u -> u.getPosition()).orElse("default");
	    assertEquals(position, user.getPosition().get());
}
5、过滤值

除了转换值之外,Optional 类也提供了按条件“过滤”值的方法。

public Optional<T> filter(Predicate< ? super T> predicate)

filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。
来看一个根据基本的电子邮箱验证来决定接受或拒绝 User(用户) 的示例:

@Test
public void whenFilter_thenOk() {
    User user = new User("anna@gmail.com", "1234");
    Optional<User> result = Optional.ofNullable(user) .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
	
6、判断对象是为null
void	ifPresent(Consumer<? super T> consumer)//如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
boolean	isPresent()//返回 true如果存在值,否则为 false 。

isPresent()一般与.get()方法合用,当view存在时,view.isPresent()值为true,通过get()方法返回对象

if(view.isPresent()) {
   return view.get();
}else {
  return null;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值