Java Consumer MethodReference for nonstatic methods

Tags: , ,



Code snippet:

class Scratch {

Map<ActionType, SomeConsumer<DocumentPublisher, String, String>> consumerMapping = Map.of(
        ActionType.REJECT, DocumentPublisher::rejectDocument, 
        ActionType.ACCEPT, DocumentPublisher::acceptDocument,
        ActionType.DELETE, DocumentPublisher::deleteDocument);
        

private void runProcess(DocumentAction action) {
    DocumentPublisher documentPublisher = DocumentPublisherFactory.getDocumentPublisher(action.getType);

    SomeConsumer<DocumentPublisher, String, String> consumer = consumerMapping.get(action.getType());
    consumer.apply(documentPublisher, "documentName", "testId1");
}

private interface DocumentPublisher {
    
    void rejectDocument(String name, String textId);

    void acceptDocument(String name, String textId);

    void deleteDocument(String name, String textId);
}

}

Which type of functionalInterface can I use instead SomeConsumer? The main issue here is that it is not static field, and the object I will only know in runtime.

I tried to use BiConsumer, however it tells me that I can not refer to non static method in this way.

Answer

From your usage here:

consumer.apply(documentPublisher, "documentName", "testId1");

It is quite clear that the consumer consumes 3 things, so it’s not a BiConsumer. You’d need a TriConsumer, which isn’t available in the standard library.

You can write such a functional interface yourself though:

interface TriConsumer<T1, T2, T3> {
    void accept(T1 a, T2 b, T3 c);
}

If the only generic parameters that you are ever going to give it is <DocumentPublisher, String, String>, I think you should name it something specific to your application, such as DocumentPublisherAction:

interface DocumentPublisherAction {
    void perform(DocumentPublisher publisher, String name, String textId);
}

Map<ActionType, DocumentPublisherAction> consumerMapping = Map.of(
        ActionType.REJECT, DocumentPublisher::rejectDocument, 
        ActionType.ACCEPT, DocumentPublisher::acceptDocument,
        ActionType.DELETE, DocumentPublisher::deleteDocument);
        

private void runProcess(DocumentAction action) {
    DocumentPublisher documentPublisher = DocumentPublisherFactory.getDocumentPublisher(action.getType);

    DocumentPublisherAction consumer = consumerMapping.get(action.getType());
    consumer.perform(documentPublisher, "documentName", "testId1");
}


Source: stackoverflow