5

I am working on this project currently. It works surprisingly well.

Yet, after re-reading the README again, I started to wonder about how to document something that is bugging me...

To quote the example, and forgetting for a moment that exceptions can be thrown, it reads:

Files.list(somePath).map(Path::toRealPath).forEach(System.out::println)

OK. Now, the method of Path involved is this one. Of course, we do not pass any LinkOption.

Again: let's forget for a moment that it throws any exception.

Stream's .map() takes a Function as an argument. This interface, for Function<T, R>, is defined as:

R apply(T t);

But the method I am using accepts no arguments. At a first glance, it does not seem to match a Function, right? Except that...

It can be written as:

path -> path.toRealPath()

It therefore looks like the mechanism used is somewhat able to invoke a method on the "stream object" if the method reference has no argument, or something like that...

I'd like to document this accordingly, and I am missing something here.

What am I missing?

fge
  • 119,121
  • 33
  • 254
  • 329

1 Answers1

3

Non-static methods have the receiver (this) object as an implicit first argument. Therefore, Class::nonStaticMethod has one more argument than you might expect.

Java Language Specification Section 15.13.1, Compile-Time Declaration of a Method Reference:

  • Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:

    • If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, the potentially applicable methods are the member methods of the type to search that have an appropriate name (given by Identifier), accessibility, arity (n or n-1), and type argument arity (derived from [TypeArguments]), as specified in §15.12.2.1.

      Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • OK, that would explain everything indeed! Hrm... Might I bugger you and ask that you edit your post with some relevant links as a Christmas present? ;) – fge Dec 24 '14 at 06:38
  • 1
    No, you can't bugger (sodomise) me, but you can bug me, sure. :-) – C. K. Young Dec 24 '14 at 06:39
  • OK, so, as a quick rundown: in the example, `ReferenceType` is `Path`; accessibility OK; name does not matter (right?); arity OK (1 or 0, here 0); and since the method reference is an instance method, the expected arity is 0, and as it happens, it returns `ReferenceType`. Am I on the right track? – fge Dec 24 '14 at 06:56
  • 1
    The name check is to find a method named `toRealPath`, in this case. A method reference of `Path::methodThatDoesNotExist` would not be valid, for example. – C. K. Young Dec 24 '14 at 06:58
  • Ah; I have somewhat overlooked the "compile" in "compile time declaration of a method reference". So, do I take it to mean that it is the role of the compiler to generate a call site with `this` (as in, the current element of the stream) as the first argument? – fge Dec 24 '14 at 07:01
  • Yes, that is what happens. – C. K. Young Dec 24 '14 at 07:03
  • 1
    That makes things clear now! Thanks a lot! Sorry for that unfortunate tongue slip and have a flowing end of a year ;) – fge Dec 24 '14 at 07:05