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 类