Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 空校验&;iPresent-名称不同但问题相同?_Java_Nullpointerexception_Return Value_Optional - Fatal编程技术网

Java 空校验&;iPresent-名称不同但问题相同?

Java 空校验&;iPresent-名称不同但问题相同?,java,nullpointerexception,return-value,optional,Java,Nullpointerexception,Return Value,Optional,我有以下Java代码: public class Browser { public URL back() { try { //simulate: fetch last URL from Stack return Math.random() < 0.5 ? new URL("http://google.de") : null; } catch(MalformedURLException e) { return null; }

我有以下Java代码:

public class Browser {

  public URL back() {
    try {
      //simulate: fetch last URL from Stack
      return Math.random() < 0.5 ? new URL("http://google.de") : null;
    } catch(MalformedURLException e) {
      return null;
    }
  }

  public void retrieveSite(URL url) {
    System.out.println(url);
    //...
  }

  public static void main(String[] args) {
    System.out.println("Normal back");
    Browser browser = new Browser();
    URL back = browser.back();
    if (back != null) browser.retrieveSite(back);
  }
}
现在,为了避免将空的
可选
传递到
检索站点
,我必须检查当前值。但是,我从检查
中得到的究竟是什么呢=空值
?我是否应该返回一个
默认值
,这样我就可以摆脱
isPresent

我还必须更改
retrieveSite()
的参数,以采用
可选的
,这被认为是不好的做法


提前感谢。

第二种方法的一个稍微不同的变体可以以更简洁的方式实现,如下所示:

static class Browser {

    // good practice to return Optional instead of a null 
    Optional<URL> back() {
        try {
            //simulate: fetch last URL from Stack
            return Math.random() < 0.5 ? Optional.of(new URL("http://google.de")) : Optional.empty();
        } catch (MalformedURLException e) {
            return Optional.empty();
        }
    }

    // avoid using Optional as a parameter to a method
    static void retrieveSite(URL url) {
        System.out.println(url);
    }

    public static void main(String[] args) {
        System.out.println("Normal back");
        Browser browser = new Browser();
        // perform a void operation if the URL is present (consuming it)
        browser.back().ifPresent(Browser::retrieveSite);
    }
}
静态类浏览器{
//返回可选值而不是空值的良好实践
可选的back(){
试一试{
//模拟:从堆栈中获取最后一个URL
返回Math.random()<0.5?可选。of(新URL(“http://google.de“”):可选。空();
}捕获(格式错误){
返回可选的.empty();
}
}
//避免将Optional用作方法的参数
静态无效检索站点(URL){
System.out.println(url);
}
公共静态void main(字符串[]args){
System.out.println(“正常背面”);
浏览器=新浏览器();
//如果存在URL,则执行作废操作(使用该URL)
browser.back().ifPresent(browser::retrieveSite);
}
}

使用
可选
时,您必须打开/测试
可选
以获取它,如果
可选
未正确使用(快速失效原则),您还将获得早期空性异常。
例如:

  public static void main(String[] args) {
    System.out.println("Normal back");
    Browser browser = new Browser(); 
   // unwraping the optional or testing it is mandatory to get the object inside in
    browser.back().ifPresent(browser::retrieveSite); 
    // for example it will not compile
    browser.retrieveSite(browser.back()); 
    // of course you could cheat by invoking Optional.get() but that is a bad practice and the absence of object will be detected as soon as the invocation 
    browser.retrieveSite(browser.back().get()); 
  }

  public void retrieveSite(URL url) {
    //...
  }
如果没有
Optional
,则如果客户端忘记显式检查no-null(
url!=null
),则NPE是可能的。对于开发人员来说,这种检查实际上没有那么引人注目,因为方法调用是获取/映射包装对象所必需的。此外,如果url参数通过各层传递,您可以在最底层发现
null
引用,这可能会使问题更复杂,难以理解和解决:

  public static void main(String[] args) {
    System.out.println("Normal back");
    Browser browser = new Browser(); 
    // No unwrapping is necessary to get the url. 
    // So the robustness of the code depends on the developer habits
    browser.retrieveSite(browser.back());     
  }

  public void retrieveSite(URL url) {        
    //...
  }

关于
Optional
的要点并不是说它不需要进行必要的检查:这是因为您不能将
Optional
视为
URL
,因此您必须明确地处理存在(或不存在)。空
URL
:您可以通过
null
传递非空
URL
,直到尝试取消引用它,您才发现。感谢您的澄清,Andy!:)您提到我应该避免使用Optional作为
retrieveSite
的参数,我读了很多遍,认为这是一种不好的做法。但是为什么会是这种情况呢?@Clay91中对此已经没有什么解释了。可能值得注意的是(明确地)通过查看
URL
的方法返回类型,您看不到它可能是
null
,而
Optional
的返回类型会立即显示它可能不存在。此外,
isPresent()
与先前版本的“is not
null
”具有相同的含义,因为在此特定示例中,
null
具有“is缺席”的含义。但是
null
并不总是具有这种意义。有时,
null
表示“我忘了初始化该字段”,在这种情况下,我永远不会切换到
可选的
。@Holger同意第一部分。对于“有时,null表示“我忘了初始化那个字段”,在这种情况下,我永远不会切换到可选。“可选”不应用于字段。所以没有真正的争论。现在为字段检查NOTNULL当然是有意义的,但这与实际用例不同:返回某些内容的方法调用。当然,您不应该为字段使用optional。但是,当您创建一个返回字段值的方法时,如果字段可以是
null
,您可以决定将该方法的返回类型设置为
可选
,如果该字段可以是
null
,也可以不设置为可选。
  public static void main(String[] args) {
    System.out.println("Normal back");
    Browser browser = new Browser(); 
    // No unwrapping is necessary to get the url. 
    // So the robustness of the code depends on the developer habits
    browser.retrieveSite(browser.back());     
  }

  public void retrieveSite(URL url) {        
    //...
  }