I was going through this question - this triggered the following set of thoughts regarding the Type Inference:
class Song {
public Integer duration;
public String artist;
public String title;
// ... getters...
}
List<Song> playlist1 = new ArrayList<>();
Collections.sort(Collections.EMPTY_LIST,
Comparator.comparing((Song p1) -> p1.getTitle())); //-----1
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle())); //----2
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration()).thenComparing(p1 -> p1.getArtist()));
//----3
Collections.sort(..)
is not a Poly Expression but a Standalone Expression:- as the return type of
.sort(...)
isvoid
- and the foremost conditions for this to be applicable for method invocation is that its return type must be Type Parameter that also appears in the arguments. - and method invocation must occur in the assignment/invocation context
- as the return type of
Comparator.comparing(...)
: is a Poly Expression as:- it occurs in the invocation context and
- has a return type that is a Type Argument also occurring as the arguments to the method.
- Thus in,
Collections.sort(playlist1, Comparator.comparing(p1 -> p1.getTitle()));
the expressionComparator.comparing(p1 -> p1.getTitle())
undergoes the type inference as:- Since the target type is
Comparator<Song>
Comparator.comparing(...)
will use the Target Type to determine the type arguments- and thus infers that
p1
is of typeSong
.
- Since the target type is
- but if we consider Expression-3 we will see Compilation Error as:
Comparator.comparing(...).thenComparing(...).thenComparing(...)
- has a target type ofComparator<Song>
- this is because for an invocation chain of this type:
ClassType.A().B().C()
the inference will have to proceed fromC() -> B() -> A() -> ClassType
- now the problem is that for the compiler - it is complete unknown that which class is C() belonging to and hence will not be able to infer the chain upto
A
. - On the contrary - if the chain had been
ClassType.A()
- the compiler can easily determine thatA()
belongs toClassType
. - and thus the compiler is unable to determine the
p1
and so on.
Is my thinking about the above points correct? or am I missing something?