2

I have a the following code:

List<Move> moves = getMoves();
moves.sort(Comparator.comparingInt(Move::getScore).reversed());

which was working great with this as the method definition in Move:

public int getScore() { return myScore; }

however I then overloaded getScore():

public int getScore(boolean doubleIt) { return myScore*2; }

and now the comparingInt() method above complains unless I do:

Comparator.<Move>comparingInt(Move::getScore).reversed()

Can someone explain why the compiler needs the additional <Move> when there are references to overloaded methods?

error message is:

incompatible types: cannot infer type-variable(s) T
(argument mismatch; invalid method reference
  incompatible types: java.lang.Object cannot be converted to boolean)

This is on MacOS Sierra, JDK is:

java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

example code: http://ideone.com/RxcXW6

Harmlezz
  • 7,972
  • 27
  • 35
BigBen
  • 1,162
  • 2
  • 11
  • 22

1 Answers1

0

You have introduced generic ambiguity and the compiler requires you to explicitly state which method you intend to be statically linked to this block. The functional notation allows for the parameter to be passed implicitly, but without specifying the class, the compiler does not know which of the two valid methods to bind. Since this isn't a polymorphic concern it will be bound at compile time, and the compiler needs explicit instructions on which to use.

Michael Hibay
  • 522
  • 3
  • 11
  • There is no parameter in this case though, as this is an unbound instance method reference. It seems like the compiler should know, especially since this works if you just remove .reversed() – BigBen Mar 28 '17 at 23:07
  • Unfortunately, it looks like the compiler is actually trying to bind to the overloaded getScore WITH the parameter based on the error. It's likely it's just picking one of the ambiguous names, but it is clearly having a problem with the type inference. Part of the magic of the functional notation is the shorthand which will actually pass parameters. Move::getScore is ambiguous because it is able to call either getScore() or getScore(boolean). It is also possible type erasure is also a problem as reversed() returns a parameterized comparator. – Michael Hibay Mar 29 '17 at 03:20