Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method reference of an object in variable vs. returned by method

I noticed that if I write something like:

View view = getView();
foo(error -> view.showError(error));

Android Studio (and probably IntelliJ too) shows the suggestion "Can be replaced with method reference".

Instead, if I write

foo(error -> getView().showError(error));

Android Studio doesn't say anything.

But in both cases I can use method references:

foo(view::showError)

and

foo(getView()::showError)

, respectively.

Are these two forms functionally different? They seem to be doing the same thing, but Android Studio seems to disagree.

like image 495
ris8_allo_zen0 Avatar asked Dec 14 '17 14:12

ris8_allo_zen0


People also ask

Can reference to an object be returned from a method?

1) Yes, it returns a reference to the object. 2) If the method is private, then it can only be called from within the class itself.

What are three ways for method reference?

Types of Method ReferencesStatic Method Reference. Instance Method Reference of a particular object. Instance Method Reference of an arbitrary object of a particular type. Constructor Reference.

Why method reference is better than lambda?

Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.


1 Answers

Note that none of these alternatives is exactly equivalent.

View view = getView();
foo(error -> view.showError(error));

will evaluate getView() immediately, but invoke showError(error) only when the function is actually evaluated (but then, each time). If view is null, a NullPoinerException will be thrown when the function is evaluated.

View view = getView();
foo(view::showError);

will evaluate getView() immediately and throw a NullPoinerException immediately if view is null. showError(error) will be invoked when the function is actually evaluated; at this time, it’s guaranteed that view is not null.

foo(error -> getView().showError(error));

will evaluate getView() only when the function is actually evaluated; it could evaluate to a different result each time. Therefore, a NullPoinerException will be thrown in a particular function evaluation if getView() returns null in this specific evaluation.

Your IDE suggests converting the first variant to the second, because it’s semantically equivalent, as long as view is not null. In contrast, the third variant is significantly different even in the non-null case, as reevaluating getView() each time may lead to different results than the early bound receiver instance. See also “What is the equivalent lambda expression for System.out::println”.

Of course, if getView() is a trivial getter invariably returning the same instance each time, the transformation would be legit, but I suppose that the IDE didn’t look into the implementation of getView() to make such a decision. It’s up to you to decide whether this change is valid in your application.

like image 163
Holger Avatar answered Oct 20 '22 02:10

Holger