7

I was trying to create a method reference to an arbitrary object, so I defined the following types:

interface I {
    boolean get(Impl impl);
}

static class Impl {
    public boolean get() {
        return true;
    }
}

Then I declared the method reference, like below:

I i = Impl::get;

When I call:

i.get(null);

I get a NullPointerException:

Exception in thread "main" java.lang.NullPointerException

Can someone explain why this happens even though the Impl reference is not used anywhere?

Boann
  • 48,794
  • 16
  • 117
  • 146
mrboieng
  • 316
  • 1
  • 9

1 Answers1

6

I think you misunderstood the meaning of this line:

I i = Impl::get;

I is a functional interface that represents a method that takes an Impl and returns a boolean, whereas get is a method that takes no parameters and returns a boolean. How does this conversion work? Well, the compiler realises that get is an instance method, and to call it you must need a Impl object. Isn't that just like a function having a parameter before it is called?

So the compiler can happily infer that you meant:

I i = impl -> impl.get();

Now the cause of the NPE should be clear.

In general, all instance methods can be thought of as static methods that take one extra parameter, of type T where T is the declaring type of that instance method.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Is there an actual conversion by the compiler from method references to lambda expressions or is this just a logical mapping? – mrboieng Nov 04 '19 at 17:29
  • 1
    @mrboieng this is just logical mapping. The bytecode for method references is different. – Sweeper Nov 04 '19 at 17:30