你的位置:首页 > Java教程

[Java教程]guava Optional


过多的使用null可能会导致大量的bugs,Google code 底层代码中,95%的集合类默认不接受null值。对null值,使用快速失败拒绝null比默认接受更好。

另外,null本身的含义很模糊。例如,对于null返回值,如Map.get(key)返回null,可能因为和key对应的值为null,也可能map中根本没有该key。null也可以用以表示失败或成功,可能代表任何事物。使用其他值而不是null可以使代码含义表达的更清楚。

尽管如此,有些地方还是应该使用null。在内存和速度方面,null是廉价的,并且在对象数组中是不可避免的。

基于以上原因,Guava大部分工具对null都设计为快速失败。另外,Guava提供了一些方便使用null的工具。

实际案例

不要在Set中使用null,也不要将null作为Map的key值,使用特殊值代替null可以让查找的语义更清晰。

如果你想把null作为Map的value,更好的办法不是将该条目放入Map中,而是应该以一个单独的Set维护“值为null”的键集合。因为Map中某个键对应的值为null和Map中没有某个键值很容易混淆。

如果需要在List中使用null,并且这个List是稀疏的,则使用Map<Integer, E>可能更好。

如果确实需要null,但null值不能和Guava的集合一起工作,则只能选择其他方式,如JDK中的Collections.unmodifiableList代替Guava中的ImmutableList。

Optional

Guava设计Optional来解决null问题,Optional<T>表示可能为null的T类型的引用。Optional实例要么包含一个非null的引用,要么什么都不包含(absent),从不会包含null值引用。在需要使用null的时候,可以用Optional代替。

Optional除了赋予null意义外,增加可读性,还在于它是一种傻瓜式的防护。Optional 迫使你积极思考引用确实的情况,因为你必须显式地从Optional 获取引用。

Optional 的可能应用方面:

  • 作为方法返回值,用于取代使用null作为返回值的情况。
  • 用于区分“unknow”(如Map不包含)和“known to have no value”(如Map包含该键,值为Optional.absent())。
  • 用于包装null引用,从而在不支持null的集合中使用。

创建Optional(均为静态方法)

Optional.of(T) 创建指定引用的Optional实例,对null值抛出NullPointException。建议直接传递常量参数。
Optional.absent() 创建引用缺失的Optional实例
Optional.fromNullable(T) 创建指定引用的Optional实例,若引用为null则表示缺失
assertEquals("training", Optional.of("training").get());Optional<String> optionalName = Optional.absent();assertFalse(optionalName.isPresent());// Non-null instanceOptional<String> optionalName = Optional.fromNullable("bob");assertEquals("bob", optionalName.get());// null instanceassertSame(Optional.absent(), Optional.fromNullable(null));

查询方法(均为非静态方法)

boolean isPresent() 如果该Optional 包含非null引用,返回true。
T get() 返回Optional 所包含的引用,若引用缺失,则抛出IllegalStateException。
T or(T) 返回Optional 所包含的引用,若引用缺失,返回默认值。
T orNull() 返回Optional 所包含的引用,若引用缺失,返回null。
Set<T> asSet() 返回Optional所包含的singleton不可变集合,若为空,返回空集合。

public void testIsPresent_no() {    assertFalse(Optional.absent().isPresent());  }  public void testIsPresent_yes() {    assertTrue(Optional.of("training").isPresent());  }  public void testGet_absent() {    Optional<String> optional = Optional.absent();    try {      optional.get();      fail();    } catch (IllegalStateException expected) {    }  }  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 testOrNull_present() {    assertEquals("a", Optional.of("a").orNull());  }  public void testOrNull_absent() {    assertNull(Optional.absent().orNull());  }  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) {    }  }




西藏旅游攻略大全西藏旅游攻略自助游西藏旅游报价价格西藏旅游景点推荐西藏旅游团报价石人山门票_河南平顶山石人山(尧山)门票价格多少钱 梵净山图片_梵净山风景图片_贵州同仁梵净山图片 沈阳故宫图片_沈阳故宫旅游图片 北京欢乐谷门票_北京欢乐谷门票价格_北京欢乐谷门票多少钱 稻城亚丁购物指南 有味道的河北梆子 五一节内地访港旅客上升超过两成 滋朴佳品:桂圆 江南大峡谷漂流几点开漂?临海江南大峡谷漂流全天都能玩吗? 临海到江南大峡谷漂流有直达公交车吗?临海到江南大峡谷漂流乘车路线? 江南大峡谷漂流安全吗?临海江南大峡谷漂流注意事项? 2015富华水上皇宫门票价格?潍坊富华水上皇宫开放时间? 深圳世界之窗2015元旦跨年演唱会?世界之窗元旦演唱会几点开始? 深圳欢乐谷2015元旦活动截止到什么时候?欢乐谷元旦有免费礼物吗? 深圳欢乐谷2015元旦狂欢活动?欢乐谷元旦优惠价? 2015元旦深圳欢乐谷有哪些好玩的?欢乐谷元旦门票价格? STB10NK60Z-1 Datasheet STB10NK60Z-1 Datasheet STI11NM60ND Datasheet STI11NM60ND Datasheet STU11NM60ND Datasheet STU11NM60ND Datasheet 上海外滩怎么走 上海外滩怎么走 上海外滩怎么走 大亚湾核电站在哪里 大亚湾核电站在哪里 大亚湾核电站在哪里 大梅沙游艇会 大梅沙游艇会 大梅沙游艇会