Guava Optional 类
Optional 用于包含非空对象的不可变对象。 Optional对象,用于不存在值表示null。这个类有各种实用的方法,以方便代码来处理为可用或不可用,而不是检查null值。
一、类声明
以下是 com.google.common.base.Optional<T> 类的声明:
@GwtCompatible(serializable = true) public abstract class Optional<T> implements Serializable
二、类方法
官方文档:https://google.github.io/guava/releases/27.0.1-jre/api/docs/com/google/common/base/Optional.html
| 方法类型 | 方法描述 |
|---|---|
static <T> Optional<T> | absent() 返回没有包含引用的Optional实例。 |
abstract Set<T> | asSet() 返回一个不可变的单集的唯一元素所包含的实例(如果存在),否则为一个空的不可变的集合。 |
abstract boolean | equals(@Nullable Object object) 如果object是Optional实例,并且包含的引用彼此相等或两者都不存在,则返回true. |
static <T> @Nullable Optional<T> | fromJavaUtil(Optional<T> javaUtilOptional) 返回给定的java.util.Optional,等效com.google.common.base.Optional值,如果参数为null,则返回null |
static <T> Optional<T> | fromNullable(T nullableReference) 如果 nullableReference 非null,返回包含该引用的Optional实例,否则返回 absent(). |
abstract T | get() 返回必须存在的实例. |
abstract int | hashCode() 返回此实例的哈希码。 |
abstract boolean | isPresent() 如果包含(非null)实例,则返回true。 |
static <T> Optional<T> | of(T reference) 返回包含给定非null引用的Optional实例。 |
abstract Optional<T> | or(Optional<? extends T> secondChoice) 如果它有一个值存在,返回Optional,否则返回secondChoice。 |
abstract T | or(Supplier<? extends T> supplier) 如果包含实例,则返回该实例,否则返回 supplier.get()。 |
abstract T | or(T defaultValue) 如果包含实例,则返回该实例,否则返回 defaultValue 默认值。 |
abstract T | orNull() 返回包含的实例(如果存在),否则返回null。 |
static <T> Iterable<T> | presentInstances(Iterable<? extends Optional<? extends T>> optionals) 从提供的选项中返回每个当前实例的值,按顺序跳过absent()的出现次数。 |
Optional<T> | toJavaUtil() 返回 java.util.Optional 等效值 |
static <T> Optional<T> | toJavaUtil(@Nullable Optional<T> googleOptional) 返回给定com.google.common.base.Optional的等效java.util.Optional值,如果参数为null,则返回null。 |
abstract String | toString() 返回此实例的字符串表示形式。 |
abstract <V> Optional<V> | transform(Function<? super T,V> function) 如果实例存在,则使用给定的函数进行转换; 否则返回 absent()。 |
三、Optional示例
import com.google.common.base.Optional;
public class OptionalDemo {
public static void main(String args[]) {
OptionalDemo demo = new OptionalDemo();
Integer value1 = null;
Integer value2 = new Integer(10);
// Optional.fromNullable:允许参数为null.
Optional<Integer> a = Optional.fromNullable(value1);
// Optional.of:如果参数为null,则抛出NullPointerException
Optional<Integer> b = Optional.of(value2);
System.out.println(demo.sum(a, b));
}
public Integer sum(Optional<Integer> a, Optional<Integer> b) {
// Optional.isPresent:检查值是否存在
System.out.println("First parameter is present: " + a.isPresent());
System.out.println("Second parameter is present: " + b.isPresent());
// Optional.or:如果存在则返回值,否则返回传递的默认值
Integer value1 = a.or(new Integer(0));
// Optional.get:获取值,此时有值存在
Integer value2 = b.get();
return value1 + value2;
}
}执行结果
First parameter is present: false Second parameter is present: true 10
四、使用 Optional 的意义在哪儿?
使用 Optional 除了赋予 null 语义,增加了可读性,最大的优点在于它是一种傻瓜式的防护。Optional 迫使你积极思考引用缺失的情况,因为你必须显式地从 Optional 获取引用。直接使用 null 很容易让人忘掉某些情形,尽管 FindBugs 可以帮助查找 null 相关的问题,但是我们还是认为它并不能准确地定位问题根源。
如同输入参数,方法的返回值也可能是 null。和其他人一样,你绝对很可能会忘记别人写的方法 method(a,b) 会返回一个 null,就好像当你实现 method(a,b) 时,也很可能忘记输入参数 a 可以为 null。将方法的返回类型指定为 Optional,也可以迫使调用者思考返回的引用缺失的情形。
五、其他处理 null 的便利方法
当你需要用一个默认值来替换可能的 null,请使用 Objects.firstNonNull(T, T)方法。如果两个值都是 null,该方法会抛出 NullPointerException。Optional 也是一个比较好的替代方案,例如:Optional.of(first).or(second).
还有其它一些方法专门处理null或空字符串:Strings.emptyToNull(String),Strings.nullToEmpty(String),Strings.isNullOrEmpty(String)。我们想要强调的是,这些方法主要用来与混淆 null/空 的API进行交互。当每次你写下混淆 null/空 的代码时,Guava团队都泪流满面。(好的做法是积极地把null和空区分开,以表示不同的含义,在代码中把null和空同等对待是一种令人不安的坏味道。
六、测试类
package com.example.guava;
import com.google.common.base.*;
import com.google.common.collect.ImmutableList;
import junit.framework.TestCase;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.google.common.truth.Truth.assertThat;
public class OptionalTests extends TestCase {
/**
* 1、toJavaUtil 静态
*/
public void testToJavaUtil_static() {
Optional<String> str = Optional.of("abc");
assertNull(Optional.toJavaUtil(null));
assertEquals("abc", Optional.toJavaUtil(str).get());
assertEquals(java.util.Optional.empty(), Optional.toJavaUtil(Optional.absent()));
assertEquals(java.util.Optional.of("abc"), Optional.toJavaUtil(Optional.of("abc")));
}
/**
* 2、toJavaUtil 实例
*/
public void testToJavaUtil_instance() {
assertEquals(java.util.Optional.empty(), Optional.absent().toJavaUtil());
assertEquals(java.util.Optional.of("abc"), Optional.of("abc").toJavaUtil());
}
/**
* 3、fromJavaUtil
*/
public void testFromJavaUtil() {
assertNull(Optional.fromJavaUtil(null));
assertEquals(Optional.absent(), Optional.fromJavaUtil(java.util.Optional.empty()));
assertEquals(Optional.of("abc"), Optional.fromJavaUtil(java.util.Optional.of("abc")));
}
/**
* 4、absent
*/
public void testAbsent() {
Optional<String> optionalName = Optional.absent();
assertFalse(optionalName.isPresent());
// 异常
try {
optionalName.get();
fail();
} catch (IllegalStateException expected) {
}
}
/**
* 5、of
*/
public void testOf() {
assertEquals("tingfeng", Optional.of("tingfeng").get());
// 空指针异常
try {
Optional.of(null);
fail();
} catch (NullPointerException expected) {
}
}
/**
* 6、fromNullable 取值
*/
public void testFromNullable() {
Optional<String> optionalName = Optional.fromNullable("tingfeng");
assertEquals("tingfeng", optionalName.get());
}
public void testFromNullable_null() {
System.out.println(Optional.absent()); // Optional.absent()
System.out.println(Optional.fromNullable(null)); // Optional.absent()
assertSame(Optional.absent(), Optional.fromNullable(null));
}
/**
* 7、isPresent 判断
*/
public void testIsPresent() {
assertFalse(Optional.absent().isPresent());
assertTrue(Optional.of("tingfeng").isPresent());
}
/**
* 8、get - or 取值
*/
public void testGet_present() {
assertEquals("training", Optional.of("training").get());
}
public void testOr_T_present() {
assertEquals("a", Optional.of("a").or("default"));
}
public void testOr_T_absent() {
assertEquals("default", Optional.absent().or("default"));
}
public void testOr_supplier_present() {
assertEquals("a", Optional.of("a").or(Suppliers.ofInstance("fallback")));
}
public void testOr_supplier_absent() {
assertEquals("fallback", Optional.absent().or(Suppliers.ofInstance("fallback")));
}
public void testOr_nullSupplier_absent() {
Supplier<Object> nullSupplier = Suppliers.ofInstance(null);
Optional<Object> absentOptional = Optional.absent();
try {
absentOptional.or(nullSupplier);
fail();
} catch (NullPointerException expected) {
}
}
public void testOr_nullSupplier_present() {
Supplier<String> nullSupplier = Suppliers.ofInstance(null);
assertEquals("a", Optional.of("a").or(nullSupplier));
}
public void testOr_Optional_present() {
assertEquals(Optional.of("a"), Optional.of("a").or(Optional.of("fallback")));
}
public void testOr_Optional_absent() {
assertEquals(Optional.of("fallback"), Optional.absent().or(Optional.of("fallback")));
}
public void testOrNull_present() {
assertEquals("a", Optional.of("a").orNull());
}
public void testOrNull_absent() {
assertNull(Optional.absent().orNull());
}
/**
* 9、asSet 只读集合对象
*/
public void testAsSet_present() {
Set<String> expected = Collections.singleton("a");
assertEquals(expected, Optional.of("a").asSet());
}
public void testAsSet_absent() {
assertTrue("Returned set should be empty", Optional.absent().asSet().isEmpty());
}
public void testAsSet_presentIsImmutable() {
Set<String> presentAsSet = Optional.of("a").asSet();
try {
presentAsSet.add("b");
fail();
} catch (UnsupportedOperationException expected) {
}
}
public void testAsSet_absentIsImmutable() {
Set<Object> absentAsSet = Optional.absent().asSet();
try {
absentAsSet.add("foo");
fail();
} catch (UnsupportedOperationException expected) {
}
}
/**
* 10、transform 转换
*/
public void testTransform_absent() {
assertEquals(Optional.absent(), Optional.absent().transform(Functions.identity()));
assertEquals(Optional.absent(), Optional.absent().transform(Functions.toStringFunction()));
}
public void testTransform_presentIdentity() {
assertEquals(Optional.of("a"), Optional.of("a").transform(Functions.identity()));
}
public void testTransform_presentToString() {
// 转换类型
assertEquals(Optional.of("42"), Optional.of(42).transform(Functions.toStringFunction()));
}
public void testTransform_present_functionReturnsNull() {
try {
Optional<String> unused =
Optional.of("a")
.transform(
new Function<String, String>() {
@Override
public String apply(String input) {
return null;
}
});
System.out.println(unused);
fail("Should throw if Function returns null.");
} catch (NullPointerException expected) {
expected.printStackTrace();
}
}
public void testTransform_absent_functionReturnsNull() {
assertEquals(
Optional.absent(),
Optional.absent()
.transform(
new Function<Object, Object>() {
@Override
public Object apply(Object input) {
return null;
}
}));
}
/**
* 11、toString
*/
public void testToString_absent() {
assertEquals("Optional.absent()", Optional.absent().toString());
}
public void testToString_present() {
assertEquals("Optional.of(training)", Optional.of("training").toString());
}
/**
* 12、presentInstances
*/
public void testPresentInstances_allPresent() {
List<Optional<String>> optionals = ImmutableList.of(Optional.of("a"), Optional.of("b"), Optional.of("c"));
assertThat(Optional.presentInstances(optionals)).containsExactly("a", "b", "c").inOrder();
}
public void testPresentInstances_allAbsent() {
List<Optional<Object>> optionals = ImmutableList.of(Optional.absent(), Optional.absent());
assertThat(Optional.presentInstances(optionals)).isEmpty();
}
public void testPresentInstances_somePresent() {
List<Optional<String>> optionals = ImmutableList.of(Optional.of("a"), Optional.absent(), Optional.of("c"));
assertThat(Optional.presentInstances(optionals)).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_callingIteratorTwice() {
List<Optional<String>> optionals = ImmutableList.of(Optional.of("a"), Optional.<String>absent(), Optional.of("c"));
Iterable<String> onlyPresent = Optional.presentInstances(optionals);
assertThat(onlyPresent).containsExactly("a", "c").inOrder();
}
public void testPresentInstances_wildcards() {
List<Optional<? extends Number>> optionals = ImmutableList.<Optional<? extends Number>>of(Optional.<Double>absent(), Optional.of(2));
Iterable<Number> onlyPresent = Optional.presentInstances(optionals);
assertThat(onlyPresent).containsExactly(2).inOrder();
}
}七、相关文章
未经允许请勿转载:程序喵 » Google Guava 快速入门 —— 【基础】Optional 类
程序喵