FAS FAS - 10 months ago 24
Java Question

Call a method on the return value of a method reference

I have a stream of files that I want to filter based on the ending of the file name:

public Stream<File> getFiles(String ending) throws IOException {
return Files.walk(this.path)
.filter(file -> file.getName().endsWith(ending));

While the lambda in the last line is not bad, I thought I could use method references there as well, like so:


Or alternatively wrapped in parentheses. However, this fails with
The target type of this expression must be a functional interface

Can you explain why this doesn't work?


Can you explain why this doesn't work?

Method references are syntactical sugar for a lambda expression. For example, the method reference File::getName is the same as (File f) -> f.getName().

Lambda expressions are "method literals" for defining the implementation of a functional interface, such as Function, Predicate, Supplier, etc.

For the compiler to know what interface you are implementing, the lambda or method reference must have a target type:

// either assigned to a variable with =
Function<File, String> f = File::getName;
// or assigned to a method parameter by passing as an argument
// (the parameter to 'map' is a Function)

or (unusually) cast to something:

((Function<File, String>) File::getName)

Assignment context, method invocation context, and cast context can all provide target types for lambdas or method references. (In all 3 of the above cases, the target type is Function<File, String>.)

What the compiler is telling you is that your method reference does not have a target type, so it doesn't know what to do with it.