Search code examples
javafunctional-programmingvariadic-functionsfunctional-interface

Consumer with varargs


Suggest the following:

  Consumer<Object[]> consumer = (args) -> { /* Do something */ }

To make use of the consumer, I have to create an Object array. So, I'd have to write something like

  consumer.accept(new Object[]{ object0, object1, ... });

Obviously, I'd rather have something like

  Consumer<Object...> consumer = (args) -> { /* Do something */ }
  consumer.accept(object0, object1, ...);

Is something like this possible?


Solution

  • Variable arity parameter (varargs) is a syntactic element, a special token indicating that a method (or a constructor) expects 0 or more arguments of that type. And these arguments will be wrapped by an array (so that technically they will constitute a single argument) when the method gets executed.

    Its usage is limited: a method can have only one parameter of variable arity and it must be defined in the last position.

    Variable arity parameter isn't a type by itself. If you'll try to use eclipses ... anywhere apart from the last position of a method (constructor) declaration, you'll get a compile error (take a look at JLS for more information).

    In order to use a variable number of arguments in a function, you can define a functional interface with a method of variable arity. And this method is the only place where elipses ... needs to be used.

    @FunctionalInterface
    public interface MyConsumer<T> {
        void accept(T... items);
    }
    
    MyConsumer<String> myConsumer = items -> Stream.of(items).forEach(System.out::println);
    
    myConsumer.accept("A", "B", "C");
    

    Will give an output:

    A
    B
    C