Java 可选类型返回空值

Java 可选类型返回空值,java,nullpointerexception,null,optional,Java,Nullpointerexception,Null,Optional,我有一节这样的课 public class SomeClass { private Optional<String> testString; public SomeClass() { populateFields(); } public Optional<String> getTestString() { return testString; } private void populateFields() {

我有一节这样的课

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();
     }
  }

}
公共类SomeClass{
私有可选测试字符串;
公共类(){
populateFields();
}
公共可选getTestString(){
返回testString;
}
私有void populateFields(){
如果(//此处出现错误){
testString=返回soOptionalString()的函数;
}
}
}
现在instanceOfSomeClass.getTestString()返回null。Optional不应该总是包含非null值或为空吗?我正在尝试或避免使用isNull()并在调用方中使用isEmpty()

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


请说明这种情况;以及oracle文档中可选类型的正确用法?

可以包含或不包含非空值的容器对象

因此,如果变量设置为null,则返回null。
更多信息

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


Optional
不是魔术,它是一个与任何其他对象一样的对象,
Optional
引用本身可以为空。
可选的内容不能为空。

来自Java文档:

可以包含或不包含非空值的容器对象。如果 值存在,isPresent()将返回true,get()将返回 价值

尽管YourClass的构造函数没有实例化可选类,这也是它为null的原因

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

来源:

这是因为您首先需要一个类为
Optional
的对象,并且代码只有一个类型为
Optional
的引用,只要您不初始化它,它就是
null
。用空/不存在的值按以下方式声明(并初始化)
testString

private Optional<String> testString= Optional<String>.empty() ;
如果您已经有了一个
字符串
值作为开始(我们称之为
originalString
),那么有3个主要选项:

  • 使用
    private Optional testString=Optional.of(originalString)初始化
    testString
    (如果
    originalString
    null
    ,则会产生
    NullPointerException
  • 使用
    Optional.ofNullable(originalString)
    ,如果
    originalString
    null,则生成空的/不存在的
    Optional
  • 通过前面两个方法之一直接参考方法
    getTestString
    中的
    originalString
    return Optional.ofNullable(originalString);
    )。不需要
    testString
    成员。实际上,我并不推荐这种做法

  • 底线是,虽然实际的
    可选
    对象不能包含
    null
    值,但对
    可选
    的引用肯定可以(尤其是在未初始化时)。根据经验,
    Optional
    引用应始终使用
    Optional.empty()
    初始化,如果不是实际的“present”/“non-empty”值。

    我总是喜欢将类的内部字段存储为它们的实际值,并在getter方法中使用
    return Optional.ofNullable(theField)
    。这确保该方法始终返回某种类型的可选值。换句话说,您永远不会遇到这样的情况:本应返回optional的方法返回null

    因此,在你的情况下:

    private String testString;
    
    ...
    
    public Optional<String> getTestString() {
          return Optional.ofNullable(testString);
    }
    
    私有字符串testString;
    ...
    公共可选getTestString(){
    返回可选的.ofNullable(testString);
    }
    

    除了“永不返回null”的好处之外,当使用Gson之类的东西将类的实例封送为JSON之类的格式时,这种方法也应该更加规范。我没有用Java8 optionals尝试过Gson,但是使用Guava optionals,如果没有类型适配器,它们无法很好地序列化为JSON。如果您存储原始值,然后在getter方法中用Optional包装它们,它们将以您期望的方式序列化为JSON。

    您可以初始化
    testString
    private Optional testString=new Optional…
    @helpYou-或者更确切地说,使用静态工厂方法:
    Optional.缺席()
    如果您使用的是Guava optionals或Java 8 optionals的
    Optional.empty()
    。Optional没有特殊的魔力-它是一个与其他任何类一样的类。这意味着可选引用(与所有引用一样)的默认值为null。
    Optional
    不公开构造函数;您不能执行
    newoptional
    。这意味着我应该首先将returnsooptionalstring()函数返回的可选值转换为字符串。所以它就像可选的字符串一样。这是个好主意吗?好吧,这取决于使用情况。在我的方法中增加了一个对象创建步骤。在99.99%的情况下使用这种方法,这并不重要,但是如果您在对性能非常敏感的情况下每秒调用此方法1000次,这种方法可能会太昂贵。如果您确实存在对性能敏感的情况,请定义最低性能阈值,并对这两种方法进行测量,以查看是否有性能原因不这样做。但很有可能,你不应该被PerformanceAnks的狗禁止。这是一个大数据环境,该代码是批处理程序的一部分,该批处理程序每天运行和处理约600万条记录(目前)。在这种情况下,我应该倾向于使用可选的.empty()?是否正在为所有这些记录调用该方法?D
    private var testString= Optional.empty<String>() ;
    
    private String testString;
    
    ...
    
    public Optional<String> getTestString() {
          return Optional.ofNullable(testString);
    }