Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java vararg pass lambda and values

I'm trying to unite lambdas and simple values in varag.

public static void Log(String format, Object ... args) {
    final Object[] fmt = new Object[ args.length ];
        for(int i = 0; i < args.length; i++)
            fmt[i] = args[i] instanceof Supplier  ?
                     ( (Supplier) args[i] ).get() :
                     args[i];
    final String s = String.format( format, fmt );
    System.err.println( s );
}

final Supplier
    s = () -> "aaa",
    d = () -> 111;
Log( "%s %d %s %d", "bbb", 222, s, d );    // OK, OUTPUT: bbb 222 aaa 111
Log( "%s %d %s %d", "bbb", 222, () -> "aaa", () -> 111 );  // COMPILE FAIL

ERROR: method Log cannot be applied to given types; REQUIERED String,Object[] found: String,String,int,()->"aaa",()->111 REASON: varargs mismatch; Object is not a functional interface

Is it possible to pass both lambdas and values to vararg?

like image 829
Dmitry Avatar asked Oct 17 '16 12:10

Dmitry


People also ask

Is it good to use varargs in Java?

Varargs are useful for any method that needs to deal with an indeterminate number of objects. One good example is String. format . The format string can accept any number of parameters, so you need a mechanism to pass in any number of objects.

How many values can be accommodated by Varargs in Java?

There can be only one variable argument in a method. Variable argument (Varargs) must be the last argument.

Can Varargs be used in abstract method?

A method with a varargs annotation produces a forwarder method with the same signature (args: Array[String])Unit as an existing method. And of course putting the annotation only on the bar in Baz means we can't use the forwarder from a Bar instance.


1 Answers

The problem is in the error message

Object is not a functional interface

You can only create a lambda for a functional interfaces (one with exactly one abstract method) Object is not an interface and it doesn't have any abstract methods so you can't create a lambda of this type. What you can do is

Log( "%s %d %s %d", "bbb", 222, (Supplier) () -> "aaa", (Supplier) () -> 111 );  

This way the compiler knows what sort of lambda you intended to implement.

By comparison you could write the following and this would behave differently in your method.

Log( "%s %d %s %d", "bbb", 222, (Callable) () -> "aaa", (Callable) () -> 111 );  
like image 171
Peter Lawrey Avatar answered Oct 03 '22 06:10

Peter Lawrey