Reputation: 413
I have the following code:
public class RefDemo {
static class Demo implements Runnable {
public Demo() {
System.out.println(this.toString() + "-----");
}
@Override
public void run() {
System.out.println("run");
}
}
public static void main(String[] args) {
Runnable runnable = Demo::new; // lambda ref constructor method
runnable.run(); // does not do anything
System.out.println(runnable);
Runnable demo = new Demo(); // using new to create a Demo instance
demo.run();
System.out.println(demo);
}
}
Which prints:
RefDemo$Demo@7291c18f----- // lambda run constructor method print
RefDemo$$Lambda$1/793589513@34a245ab // main method print
RefDemo$Demo@7cc355be-----
run
RefDemo$Demo@7cc355be
I don't know why the code does not print run
when calling runnable.run();
Why does that happen?
Upvotes: 23
Views: 6371
Reputation: 16246
The lines:
Runnable runnable = Demo::new;
runnable.run();
Are equivalent to:
Runnable runnable = new Runnable() {
@Override
public void run() {
new Demo(); // Creates an instance of the Demo class, and nothing more
}
};
runnable.run();
At the same time, your intention was to invoke the run
method from the Demo
class through a method reference. Therefore, I assume you meant the following:
Runnable runnable = new Demo()::run;
runnable.run();
// But, this is a little bit redundant...
The above code is equivalent to:
Demo demo = new Demo();
Runnable runnable = new Runnable() {
@Override
public void run() {
demo.run();
}
};
runnable.run();
P.S. You don't really need a method reference here, so just write:
new Demo().run();
Or:
Runnable demo = new Demo();
demo.run();
Upvotes: 11
Reputation: 1580
This code
Runnable runnable = Demo::new;
Is equivalent to this code
Runnable runnable = new Runnable() {
@Override
public void run() {
new Demo();
}
};
So you are not referring to the run
method of Demo
but to the constructor.
Upvotes: 42
Reputation: 57154
You are simply using Runnable
in too many places and confusing yourself. The following code makes it a bit clearer what is happening:
public class RefDemo {
static class Demo {
public Demo() {
System.out.println(this.toString() + "-----");
}
public void something() {
System.out.println("something");
}
}
public static void main(String[] args) {
Runnable runnable = Demo::new;
runnable.run();
System.out.println(runnable);
Demo demo = new Demo();
demo.something();
System.out.println(demo);
}
}
Runnable runnable = Demo::new;
means that you now have a reference to the constructor of Demo
(which still works after dropping the conformance to the Runnable
interface). And you store that reference in a variable of type Runnable
which only works because their functional interfaces are compatible. Calling run
on that reference then simply calls the constructor, not the run
/ something
method of Demo
.
Upvotes: 20
Reputation: 393936
Demo::new
is the constructor of the Demo
class. Since you assign it to a reference to the Runnable
interface, calling runnable.run()
invokes the constructor and creates a new Demo
instance. The run()
method is not executed.
If you want to define a Runnable
instance that calls Demo
's run()
method using a method reference, you can write:
Runnable runnable = new Demo()::run;
Of course, since Demo
already implements Runnable
, it's much simpler to just write:
Runnable runnable = new Demo();
Upvotes: 6