可选类型 returns 空值

Optional Type returns a null value

我有一个class这样的。

public class SomeClass {

  private Optional<String> testString;

  public SomeClass() { 
      populateFields();
  }

  public Optional<String> getTestString() {
      return testString;
  }

  private void populateFields() {
     if(//something is going false here){
       testString = functionThatReturnsOptionalString();
     }
  }

}

现在 instanceOfSomeClass.getTestString() returns 无效。 Optional 不是总是应该包含非空值或为空吗?我正在尝试或避免使用 isNull() 并在我的调用方中使用 isEmpty()。

如果我在populateFields() 的第一行打断点,然后检查当时testString 中的值,它显示该值为null。这意味着该字段的默认值(在分配任何内容之前)为空。

请说明情况;也许 Optional 的正确用法?

来自 Optional 类型的 oracle 文档:

A container object which may or may not contain a non-null value.

所以,是的,如果变量设置为 null,它将 return null。 更多信息 here

Optional 总是包含非空值或为空,是的,但是您没有 Optional,您有一个指向 null 的 Optional 类型的引用。您需要初始化 testString,例如至 Optional.empty().

Optional 不是魔法,它和其他对象一样是一个对象,Optional 引用本身可以为空。就是Optional的内容不能为null。

来自 Java 文档:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

尽管 YourClass 的构造函数没有实例化您的 Optional class 这就是为什么它为 null 的原因。

public SomeClass() {  
    this.testString = Optional.empty();
} 

来源:http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

那是因为您首先需要 class Optional<String>object 而代码只有 reference类型 Optional<String>,只要不初始化它就是 null。通过以下方式使用 empty/absent 值声明(并初始化)testString

private Optional<String> testString= Optional<String>.empty() ;

或使用类型推断:

private Optional<String> testString= Optional.empty<>() ;
private Optional testString= Optional.empty<String>() ;

现在您有一个实际的 Optional 对象附加到引用 testString 而不是 null。 Java 10 会允许更短

private var testString= Optional.empty<String>() ;

如果您已经有一个 String 值开始(我们称之为 originalString),则有 3 个主要选项:

  1. private Optional<String> testString= Optional.of(originalString) ; 初始化 testString(如果 originalStringnull,这将产生 NullPointerException
  2. 使用 Optional.ofNullable(originalString),如果 originalStringnull,它会产生 empty/absent Optional
  3. 通过前面两种方法之一直接引用方法getTestString中的originalString(例如return Optional.ofNullable(originalString) ;)。不需要 testString 成员。我实际上一般推荐这种做法。

最重要的是,虽然实际的 Optional 对象不能包含 null 值,但 Optional 的引用 绝对可以(特别是在未初始化时)。根据经验,如果 Optional 引用不是实际的“存在”/“非空”值,则应始终使用 Optional.empty() 进行初始化。

我一向喜欢把class的内部字段存储为它们的实际值,在getter方法中使用return Optional.ofNullable(theField)。这确保该方法总是 return 某种类型的可选。换句话说,你永远不会 运行 进入你的方法应该 return 一个可选的方法是 returning null.

的情况

所以在你的情况下:

private String testString;

...

public Optional<String> getTestString() {
      return Optional.ofNullable(testString);
}

除了 'never returning null' 的好处之外,这种方法在使用 Gson 之类的东西将 class 的实例编组为 JSON 之类的格式时也应该表现得更好。我还没有尝试过使用 Java 8 个可选值的 Gson,但是对于 Guava 可选值,如果没有类型适配器,它们就不能很好地序列化到 JSON 中。如果您要存储原始值,然后在 getter 方法中用 Optionals 包装它们,它们将以您期望的方式序列化为 JSON。