By user1722245


2019-01-07 10:15:01 8 Comments

Why doesn't the first of the following examples work?

  • run(R::new); method R.run is not called.
  • run(new R()); method R.run is called.

Both examples are compiled-able.

public class ConstructorRefVsNew {

  public static void main(String[] args) {
      new ConstructorRefVsNew().run(R::new);
      System.out.println("-----------------------");
      new ConstructorRefVsNew().run(new R());
  }

  void run(Runnable r) {
      r.run();
  }

  static class R implements Runnable {

      R() {
          System.out.println("R constructor runs");
      }

      @Override
      public void run() {
          System.out.println("R.run runs");
      }
  }
}

The output is:

  R constructor runs
  -----------------------
  R constructor runs
  R.run runs

In the first example, the R constructor is called, it returns lambda (which is not object):

But then how is it possible, that the example is compiled successfully?

4 comments

@ernest_k 2019-01-07 10:18:34

Your run method takes a Runnable instance, and that explains why run(new R()) works with the R implementation.

R::new is not equivalent to new R(). It can fit the signature of a Supplier<Runnable> (or similar functional interfaces), but R::new cannot be used as a Runnable implemented with your R class.

A version of your run method that can takeR::new could look like this (but this would be unnecessarily complex):

void run(Supplier<Runnable> r) {
    r.get().run();
}

Why does it compile?

Because the compiler can make a Runnable out of the constructor call, and that would be equivalent to this lambda expression version:

new ConstructorRefVsNew().run(() -> {
    new R(); //discarded result, but this is the run() body
});

The same applies to these statements:

Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);

But, as you can notice, the Runnable created with R::new does just call new R() in its run method body.


A valid use of a method reference to execute R#run could use an instance, like this (but you'd surely rather use the r instance directly, in this case):

R r = new R();
new ConstructorRefVsNew().run(r::run);

@user1722245 2019-01-07 10:21:14

Should we assume, that java compiler created from my method run(Runnable r) -> run(Supplier<Runnable> r)?

@ernest_k 2019-01-07 10:36:20

@user1722245 I edited the answer. The compiler made () -> {new R();} out of R::new in that context.

@Andrew Tobilko 2019-01-07 10:28:53

Compare two calls:

((Runnable)() -> new R()).run();
new R().run();

By ((Runnable)() -> new R()) or ((Runnable) R::new) , you create a new Runnable which does nothing1.

By new R(), you create an instance of the R class where the run method is well-defined.


1 Actually, it creates an object of R which has no impact on execution.


I was thinking of treating 2 invocations identically without modifying the main method. We would need to overload run(Runnable) with run(Supplier<Runnable>).

class ConstructorRefVsNew {

    public static void main(String[] args) {
        new ConstructorRefVsNew().run(R::new);
        System.out.println("-----------------------");
        new ConstructorRefVsNew().run(new R());
    }

    void run(Runnable r) {
        r.run();
    }

    void run(Supplier<Runnable> s) {
        run(s.get());
    }

    static class R implements Runnable { ... }
}

@Henry 2019-01-07 10:23:11

The first example:

new ConstructorRefVsNew().run(R::new);

is more or less equivalent to:

new ConstructorRefVsNew().run( () -> {new R();} );

The effect is you just create an instance of R but do not call its run method.

@user1722245 2019-01-07 10:29:57

It means, that I have two nested runnable. On the first method run is called only.

@RealSkeptic 2019-01-07 10:24:55

The run method expects a Runnable.

The easy case is new R(). In this case you know the result is an object of type R. R itself is a runnable, it has a run method, and that's how Java sees it.

But when you pass R::new something else is happening. What you tell it is to create an anonymous object compatible with a Runnable whose run method runs the operation you passed it.

The operation you passed it is not R's run method. The operation is the costructor of R. Thus, it's like you have passed it an anonymous class like:

new Runnable() {

     public void run() {
         new R();
     }
}

(Not all the details are the same, but this is the closest "classical" Java construct ).

R::new, when called, calls new R(). Nothing more, nothing less.

Related Questions

Sponsored Content

4 Answered Questions

[SOLVED] Is it possible to have a constructor with void return type?

  • 2015-03-22 03:12:52
  • Naresh Kumar
  • 316 View
  • -4 Score
  • 4 Answer
  • Tags:   java constructor

29 Answered Questions

[SOLVED] Why are static variables considered evil?

  • 2011-08-11 13:14:37
  • Vamsi Emani
  • 210525 View
  • 569 Score
  • 29 Answer
  • Tags:   java static

41 Answered Questions

[SOLVED] "implements Runnable" vs "extends Thread" in Java

4 Answered Questions

[SOLVED] Why is "final" not allowed in Java 8 interface methods?

6 Answered Questions

[SOLVED] Java - Method executed prior to Default Constructor

  • 2015-09-21 06:27:44
  • Rohit Nigam
  • 4319 View
  • 26 Score
  • 6 Answer
  • Tags:   java constructor

24 Answered Questions

[SOLVED] Why can't I define a static method in a Java interface?

1 Answered Questions

[SOLVED] Is it possible to write a program in Java without main() using JDK 1.7 or higher?

  • 2014-05-19 17:41:18
  • user1852957
  • 1880 View
  • 3 Score
  • 1 Answer
  • Tags:   java jdk1.6 java-8

2 Answered Questions

[SOLVED] ExecutorService workStealingPool and cancel method

1 Answered Questions

[SOLVED] How Runnable is created from Java8 lambda

  • 2015-12-01 17:54:49
  • robjwilkins
  • 25750 View
  • 16 Score
  • 1 Answer
  • Tags:   java lambda java-8

2 Answered Questions

[SOLVED] Why does Thread implement Runnable?

  • 2013-08-19 03:21:33
  • Boann
  • 1850 View
  • 31 Score
  • 2 Answer
  • Tags:   java runnable

Sponsored Content