我注意到,如果我编写类似以下内容的内容:
View view = getView();
foo(error -> view.showError(error));
Android Studio(可能还有IntelliJ)显示了建议“可以用方法引用代替”。
相反,如果我写
foo(error -> getView().showError(error));
Android Studio什么也没说。
但是在两种情况下,我都可以使用方法引用:
foo(view::showError)
和
foo(getView()::showError)
, 分别。
这两种形式在功能上是否不同?他们似乎在做同样的事情,但是Android Studio似乎不同意。
最佳答案
请注意,这些选择都不完全相同。
View view = getView();
foo(error -> view.showError(error));
会立即评估
getView()
,但仅在实际评估函数时(但随后每次)才调用showError(error)
。如果view
是null
,则在评估函数时将抛出NullPoinerException
。View view = getView();
foo(view::showError);
如果
getView()
是NullPoinerException
,它将立即评估view
并立即抛出null
。实际评估函数时,将调用showError(error)
;目前,请确保view
不是null
。foo(error -> getView().showError(error));
仅在实际评估函数时才评估
getView()
;每次都会得出不同的结果。因此,如果NullPoinerException
在此特定评估中返回getView()
,则将在特定函数评估中抛出null
。您的IDE建议将第一个变体转换为第二个变体,因为它在语义上是等效的,只要
view
不是null
即可。相反,即使在非null
情况下,第三种变体也存在显着差异,因为每次重新评估getView()
可能会导致结果与早期绑定(bind)接收者实例不同。另请参阅“What is the equivalent lambda expression for System.out::println”。当然,如果
getView()
是每次都返回相同实例的简单getter,则转换是合法的,但我想IDE不会考虑getView()
的实现来做出这样的决定。由您决定此更改在您的应用程序中是否有效。