31

When using map functions in java I can do the following:

import com.example.MyClass;

someStream.map(MyClass::myStaticMethod)

but in my project we sometimes use static imports, how can I reference the myStaticMethod when the import is static?

I would think this would work but it doesn't:

import static com.example.MyClass.myStaticMethod;

someStream.map(myStaticMethod); //does not compile

Why does this not work? Am I 'stuck' with using the first example or are there other solutions.

Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
Richard Deurwaarder
  • 2,023
  • 1
  • 26
  • 40

4 Answers4

29

Let's look at the relevant part of the Java Language Specification, 15.13. Method Reference Expressions.

It lists the following ways to a create method reference:

MethodReference:
  ExpressionName :: [TypeArguments] Identifier 
  ReferenceType :: [TypeArguments] Identifier 
  Primary :: [TypeArguments] Identifier 
  super :: [TypeArguments] Identifier 
  TypeName . super :: [TypeArguments] Identifier 
  ClassType :: [TypeArguments] new 
  ArrayType :: new

Note that all of them include a :: token.

Since the argument to someStream.map(myStaticMethod) does not include ::, it is not a valid method reference.

This suggests that you do need to import MyClass (perhaps in addition to the static import, if that's your preference) and refer to the method as MyClass::myStaticMethod.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 1
    Nice way of thinking about the problem by referencing the JLS! But map can handle other arguments too, like lambda that also does not have a ::. Is there a more abstract type which represents what a map will accept as argument? Which would s – Richard Deurwaarder Aug 16 '17 at 14:58
4

Well it does not compile because the JLS says so. But that can't even compile since it would be a plain method invocation and not a method reference - which is defined ONLY using the :: notation, be it a static or instance used on.

It is an interesting aspect still, one that you can't resolve - may be at the moment. There is no language support to define something like:

MethodRef <Class, Method> ref = ...

And later use that the way you want it to. But I don't even think that would be possible, because you would also have to define the parameters types and return type somehow, because this would be needed to see if it matches multiple other places. Like Predicate<String> and Function<String, Boolean> that would potentially apply to the same method reference.

Eugene
  • 117,005
  • 15
  • 201
  • 306
3

Having a static import of a method does not influence the way you define a method reference to it.

So, if you want it to work, it should look exactly the same just like before introducing the static import:

MyClass::myStaticMethod
Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
-2

With a static import of a method you can only call but not refer to it. For stream().map() it needs a reference to a function so it can call it for every entry.

brtln
  • 46
  • 2