Why doesn't the problematic line work? The IDE says
Cannot resolve method 'identify(String[])'"
but it's right. there
public class PersonApp {
public static void main(String[] args) {
if (areValidArgs(args)) {
Operations.findAppropriateOperation(args).execute();
}
}
public static boolean areValidArgs(String[] args) {
return args.length > 0;
}
}
@Component
public class Operations {
private static Operation[] operations; // let Spring inject all beans of type Operation
@Autowired
public void setOperations(Operation[] operations) {
Operations.operations = operations;
}
public static Operation findAppropriateOperation(String[] args) {
Optional<Operation> operationOptional = Arrays.stream(operations)
.findFirst(op -> op.identify(args)); // this line is problematic
/*
If I change the statement above to
Optional<Operation> operationOptional = Arrays.stream(operations)
.filter(op -> op.identify(args))
.findFirst();
it works, but I can't stop thinking why the initial code didn't
*/
return operationOptional
.orElseThrow(() -> new IllegalArgumentException("Unsupported argument"));
}
}
@Component
@RequiredArgsConstructor
public abstract class Operation {
protected final PersonService personService;
public abstract boolean identify(String[] args); // here!
public abstract void execute();
}
// sample operation
@Component
public class CreatePersonTableOperation extends Operation {
public CreatePersonTableOperation(PersonService personService) {
super(personService);
}
@Override
public boolean identify(String[] args) {
return args.length == 1 && args[0].equals("1");
}
@Override
public void execute() {
personService.createPersonTable();
}
}
I thought maybe Arrays.stream()
returns a stream of Object
s (for example, stream.toArray()
returns an array of Object
s so streams and arrays don't get along very well), but I checked the docs, and it doesn't
public static <T> Stream<T> stream(T[] array)
Returns a sequential Stream with the specified array as its source.
Type Parameters:
T - The type of the array elements
Parameters:
array - The array, assumed to be unmodified during use
Returns:
a Stream for the array
While void Operation#identify(String[])
exists, Optional<T> Stream#findFirst(Predicate<? super T>)
does not.
Stream#findFirst()
is parameterless method.
Since there is no parameter, the Java compiler cannot infer the type of the lambda op
parameter. It can only do that if there is a SAM type available to match against.
If you want to find the first item based on a given predicate, you have to filter
the stream first:
Optional<Operation> operationOptional = Arrays.stream(operations)
.filter(op -> op.identify(args))
.findFirst();