我在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);
}
}
我想了解有关Optional
的更多信息,并重新编写此代码,以便不再需要return null
和if (back!=null)
。
这就是我得到的:
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);
}
}
}
现在,为了避免将空的Optional
传递给retrieveSite
,我必须检查当前值。但是,我从检查isPresent
而不仅仅是!=null
到底能得到什么呢?我应该返回一个default
值,以便摆脱isPresent
吗?
我还必须更改retrieveSite()
的参数以采用Optional
,这被认为是不好的做法吗?
谢谢。
答案 0 :(得分:1)
第二种方法的稍有不同的变体可以更简洁的方式实现:
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);
}
}
答案 1 :(得分:0)
使用Optional
时,您必须解包/测试Optional
才能得到它,并且如果未正确使用Optional
(快速失败原理),您还将得到早期清空的异常。 >
例如:
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) {
//...
}