Java vararg传递lambda和值

时间:2016-10-17 12:36:27

标签: java lambda variadic-functions

我试图在varag中将lambda和简单值联合起来。

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

错误:方法Log不能应用于给定类型; REQUIERED String,Object [] found:String,String,int,() - &gt;&#34; aaa&#34;,() - &gt; 111原因:varargs不匹配;对象不是功能接口

是否可以将lambdas和值传递给vararg?

3 个答案:

答案 0 :(得分:5)

问题在于错误消息

  

对象不是功能界面

你只能为一个功能接口创建一个lambda(一个只有一个抽象方法)对象不是一个接口,它没有任何抽象方法,所以你不能创建这种类型的lambda 。你能做的是

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

这样编译器就知道你想要实现什么样的lambda。

通过比较,您可以编写以下内容,这在您的方法中的行为会有所不同。

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

答案 1 :(得分:0)

问题是Object不是@FunctionalInterface。话虽如此,你可以传递一个简单的匿名实例:

Log( "%s %d %s %d", "bbb", 222, new Supplier<String>() {
            @Override
            public String get() {
                return "aaa";
            }
        }); 

如果您不想使用未经检查的强制转换,则可以使用此方法,这会导致编译器警告。

如果你仍然想要施放你的lambda,可以这样做:

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

答案 2 :(得分:0)

对于编译器,无法确定在对它们进行delcare时使用的函数接口的类型(与第一个不同,因为您在variableType中定义了它)

因此,修复将是供应商。例如。 (未经测试)

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

希望这指向正确的方向。