美文网首页
guava的Basic utilities使用介绍

guava的Basic utilities使用介绍

作者: engineer_tang | 来源:发表于2020-02-21 15:14 被阅读0次

避免使用null

不小心使用空值会导致各种各样的错误。通过研究Google代码库,我们发现大约95%的集合中不应该包含任何空值,而让这些集合快速失败而不是默默接受空值对开发人员是有帮助的。

此外,null是令人不快的模棱两可的。空返回值的含义并不明显——例如,Map.get(key)可以返回空值,原因可能是映射中的值为空,或者该值不在映射中。空可以表示失败,可以表示成功,可以表示几乎任何事情。使用空值以外的其他值可以使您的意思更清楚。

也就是说,有时使用空值是正确的。就内存和速度而言,空值很便宜,而且在对象数组中不可避免。但在应用程序代码中,与库相反,它是混淆、困难和奇怪的错误以及令人不快的歧义的主要来源——例如,当Map.get返回null时,它可能表示值不存在,或者值存在且为null。最关键的是,空值不表示空值的含义。

由于这些原因,许多Guava的实用工具类被设计成在存在空值的情况下快速失效,而不是允许使用空值,只要有一个空友好的解决方案可用。此外,Guava还提供了许多便利,使您在必须使用null时更容易使用,并帮助您避免使用null。

具体案例

如果试图在集合中使用空值或将其用作映射中的键,请不要这样做;如果在查找操作期间显式地使用特殊大小写空值,则会更清楚(不太令人惊讶)。

如果您想在映射中使用null作为值,请省略该项;保留一组单独的非null键(或null键)。很容易混淆映射包含键项(值为空)和映射没有键项的情况。最好将这些键分开,并考虑当与键关联的值为空时对应用程序意味着什么。

如果您在列表中使用的是空值——如果列表是稀疏的,您是否可以使用Map<Integer,E>?这实际上可能更有效,并且可能更准确地匹配应用程序的需求。

考虑是否有可以使用的自然“空对象”。并不总是这样。但有时。例如,如果它是一个枚举,则添加一个常量来表示您在这里所期望的空值。例如,java.math.RoundingMode有一个不必要的值来指示“不进行舍入,如果需要舍入,则抛出异常”

如果您确实需要空值,并且遇到了空的恶意集合实现的问题,请使用其他实现。例如,使用Collections.unmodifiableList(Lists.newArrayList())而不是ImmutableList。

Optional

程序员使用空值的许多情况都是为了表示某种缺失:可能在有值的地方,没有值,或者找不到值。例如,当找不到键的值时,Map.get返回null。

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

可选<T>是用非空值替换可为空的T引用的一种方法。一个可选的可以包含一个非空的T引用(在这种情况下,我们说引用是“存在的”),或者它可以不包含任何内容(在这种情况下,我们说引用是“不存在的”)。从来没有人说它“包含空值”

Optional并不打算直接模拟其他编程环境中的任何现有“option”或“maybe”构造,尽管它可能有一些相似之处。
我们在这里列出一些最常见的可选操作。

方法 描述
Optional.of(T) 生成一个非空值的Optional对象,或遇到空值进行快速失败操作。
Optional.absent() 返回某种类型的不存在的可选项.
Optional.fromNullable(T) 将给定的可能为空的引用转换为可选引用,将非空视为存在,将空视为不存在。

非静态方法

Method Description
boolean isPresent() 如果存在一个非空实例将返回True
T get() 返回包含的T实例,该实例必须存在;否则,抛出IllegalStateException。
T or(T) 返回此Optional中的当前值,如果没有,则返回指定的默认值。
T orNull() 返回此“Optional”中的当前值,如果没有,则返回“null”。“fromNullable”的逆操作。
Set<T> asSet() 返回一个不可变的singleton“Set”,其中包含此“Optional”中的实例(如果有实例),或者返回一个空的不可变集。

先决条件

Guava提供了许多先决条件检查实用工具类。我们强烈建议静态导入这些文件。
每种方法都有三种变体:
1)没有额外的参数。抛出任何异常时都不会显示错误消息。
2)一个额外的对象参数。错误消息object.toString()引发任何异常。
3)一个额外的字符串参数,具有任意数量的附加对象参数。它的行为类似于printf,但是为了GWT的兼容性和效率,它只允许使用%s指示符。
注意:checkNotNull、checkArgument和checkState有大量的重载,它们是基元参数和对象参数的组合,而不是varargs数组——这允许像上面这样的调用在大多数情况下避免基元装箱和varags数组分配。
第三种变体的示例:

checkArgument(i >= 0, "Argument was %s but expected nonnegative", i);
checkArgument(i < j, "Expected i < j, but %s >= %s", i, j);
Signature (not including extra args) Description Exception thrown on failure
checkArgument(boolean) Checks that the boolean is true. Use for validating arguments to methods. IllegalArgumentException
checkNotNull(T) Checks that the value is not null. Returns the value directly, so you can use checkNotNull(value) inline. NullPointerException
checkState(boolean) Checks some state of the object, not dependent on the method arguments. For example, an Iterator might use this to check that next has been called before any call to remove. IllegalStateException
checkElementIndex(int index, int size) Checks that index is a valid element index into a list, string, or array with the specified size. An element index may range from 0 inclusive to size exclusive. You don't pass the list, string, or array directly; you just pass its size.
Returns index. IndexOutOfBoundsException
checkPositionIndex(int index, int size) Checks that index is a valid position index into a list, string, or array with the specified size. A position index may range from 0 inclusive to size inclusive. You don't pass the list, string, or array directly; you just pass its size.
Returns index. IndexOutOfBoundsException
checkPositionIndexes(int start, int end, int size) Checks that [start, end) is a valid sub range of a list, string, or array with the specified size. Comes with its own error message. IndexOutOfBoundsException

由于某些原因,我们更喜欢滚动自己的前提条件检查,而不是例如Apache Commons的类似实用程序。简要地:

  • 静态导入后,Guava方法清晰明了。 checkNotNull明确说明正在执行的操作以及将引发的异常。
  • checkNotNull验证后返回其参数,从而允许在构造函数中使用简单的一列式:this.field = checkNotNull(field);
  • 简单的varargs“ printf样式”异常消息。(这也是我们建议继续使用checkNotNullover的原因 Objects.requireNonNull

我们建议您将先决条件分成不同的行,这可以帮助您确定调试时哪个先决条件失败。此外,您应该提供有用的错误消息,当每项检查都单独显示时,此消息会更容易。

排序

对象常用方法

当对象字段可以为空时,实现object.equals可能会很麻烦,因为您必须分别检查是否为空。使用Objects.equal可以以一种对null敏感的方式执行equals检查,而不必冒NullPointerException的风险。

Objects.equal("a", "a"); // returns true
Objects.equal(null, "a"); // returns false
Objects.equal("a", null); // returns false
Objects.equal(null, null); // returns true

hashCode
散列对象的所有字段应该更简单。Guava的Objects.hashCode(Object…)为指定的字段序列创建合理的、顺序敏感的哈希。使用Objects.hashCode(field1,field2,…,fieldn)而不是手工构建哈希。
toString
一个好的toString方法在调试中是非常宝贵的,但是编写起来很麻烦。使用MoreObjects.toStringHelper()轻松创建一个有用的toString。一些简单的例子:

// Returns "ClassName{x=1}"
   MoreObjects.toStringHelper(this)
       .add("x", 1)
       .toString();

   // Returns "MyObject{x=1}"
   MoreObjects.toStringHelper("MyObject")
       .add("x", 1)
       .toString();

@Data
@AllArgsConstructor
public class User {

    private Integer id;
    private String name;
    private Integer age;

    public String toString(){
        return MoreObjects.toStringHelper(this)
                .add("id", id)
                .add("name", name)
                .add("age", age)
                .toString();
    }
}

Throwables

Guava的Throwables 工具类可以经常简化处理异常。
Propagation(传播)
有时,当捕捉到异常时,您希望将其返回到下一个try/catch块。这通常是运行时异常或错误实例的情况,这些实例不需要try/catch块,但当您不希望try/catch块捕获时,它们可以被try/catch块捕获。
Guava提供了几个实用工具类来简化传播异常。例如:

try {
  someMethodThatCouldThrowAnything();
} catch (IKnowWhatToDoWithThisException e) {
  handle(e);
} catch (Throwable t) {
  Throwables.propagateIfInstanceOf(t, IOException.class);
  Throwables.propagateIfInstanceOf(t, SQLException.class);
  throw Throwables.propagate(t);
}

以下是Guava传播异常方法的快速总结:

Signature Explanation
RuntimeException propagate(Throwable) Propagates the throwable as-is if it is a RuntimeException or an Error, or wraps it in a RuntimeException and throws it otherwise. Guaranteed to throw. The return type is a RuntimeException so you can write throw Throwables.propagate(t) as above, and Java will realize that that line is guaranteed to throw an exception.
void propagateIfInstanceOf(Throwable, Class<X extends Exception>) throws X Propagates the throwable as-is, if and only if it is an instance of X.
void propagateIfPossible(Throwable) Throws throwable as-is only if it is a RuntimeException or an Error.
void propagateIfPossible(Throwable, Class<X extends Throwable>) throws X Throws throwable as-is only if it is a RuntimeException, an Error, or an X.

参考:https://github.com/google/guava/wiki

相关文章

网友评论

      本文标题:guava的Basic utilities使用介绍

      本文链接:https://www.haomeiwen.com/subject/sjvcqhtx.html