Null-Check & isPresent - Different name but same issue?

Clayy91 :

I have the following code in 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);
  }
}

I want to learn more about Optional and re-write this code so that return null and if (back!=null) is not required anymore.

So this is what i got:

public class Browser {

  Optional<URL> url = Optional.empty();

  public Optional<URL> back() {

    try {
      //simulate: fetch last URL from Stack
      if(Math.random()<0.5) {
        url = Optional.of(new URL("http://google.de"));
      } 
      return url;
    } catch(MalformedURLException e) {
      return url;
    }
  }

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

  public static void main(String[] args) {
    System.out.println("Normal back");
    Browser browser = new Browser();
    Optional<URL> back = browser.back();
    if(back.isPresent()) {
      browser.retrieveSite(back);
    }   
  }
}

Now in order to avoid passing an empty Optional to retrieveSite, i have to check for a present value. But what exactly am I gaining from checking for isPresent instead of just !=null? Should i return a default value instead, so i can get rid of isPresent?

Also i had to change the Parameter for retrieveSite() to take an Optional which is considered as bad practice?

Thanks in advance.

davidxxx :

With Optional you have to unwrap/test the Optional to get it and you also get early emptiness exception if Optional is not correctly used (fail fast principle).
For example :

  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) {
    //...
  }

Without Optional, a NPE is possible if the client forget to check explicitly the no nullity (url != null). This check is really less compelling for the developper that a method invocation that is mandatory to get/map the wrapped object. Besides, you can discover the null reference later in a very bottom layer if the url parameter is passed through the layers, which makes issues potentially more complicated to understand and solve :

  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) {        
    //...
  }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=156734&siteId=1