2014-09-18 78 views
1

我似乎无法使其工作。Java 8 Lambda超载

Function<Integer, Integer> test = x -> x+x; 
Function<String, String> test = x -> x+x; 

产生

重复的局部变量test

我怎样才能让这个test.apply(5)收益10 test.apply("5")回报“55”

+0

而不是使用函数你可以简写为UnaryOperator TechTrip 2014-09-18 22:05:46

回答

9

test是一个变量,它不是一个方法。你不能重载一个变量。

您可能会尝试使用两个方法签名创建接口,但结果不会是功能接口,并且您无法使用lambda实现它。我们再次失败。

+0

所以,无论如何,没有办法做'test.apply(5)'和'test.apply(“5”)'并得到我描述的行为在问题中? – SGr 2014-09-18 21:20:34

+0

你可以,但绝对不能使用lambda来实现'test :: apply'。自定义界面的行人执行将是唯一的方法。 – 2014-09-18 21:21:04

6

简而言之:你不能。

你在做什么不是超载。它创建了两个不同的实例,其中包含冲突名称的界面。

这相当于做:

int a = 1; 
int a = 2; 

在同一范围内,同样是非法的。

超载会发生,如果你能在Function接口两个apply定义 - 一个以String参数,一个以int。你不能(轻易地)修改java中的现有接口。

4

您不能有一个test变量实现Function<Integer, Integer>Function<String, String>(这是相同的接口)的匿名函数。

但是,您可以使用重载apply方法的嵌套类,并最终使用lambda函数构造它。这个嵌套类不需要(也不能)实现Function<Integer, Integer>Function<String, String>。但作为显示在下面的例子中,你其实并不需要实现这些接口:

static class FunctionOverload { 
    private final Function<String, String> stringFunction; 
    private final Function<Integer, Integer> integerFunction; 

    FunctionOverload(Function<String, String> stringFunction, Function<Integer, Integer> integerFunction) { 
     this.stringFunction = stringFunction; 
     this.integerFunction = integerFunction; 
    } 

    public String apply(String string) { 
     return this.stringFunction.apply(string); 
    } 

    public Integer apply(Integer integer) { 
     return this.integerFunction.apply(integer); 
    } 
} 

public static void main(String[] args) { 
    FunctionOverload test = new FunctionOverload(x -> x + x, x -> x + x); 
    test.apply("5"); 
    test.apply(5); 
    Stream.of("5").map(test::apply); 
    Stream.of(5).map(test::apply); 
} 
+0

这是一个优雅的解决方案,非常酷。尤其像使用方法引用。 – TechTrip 2014-09-18 21:49:18

+1

要从流中提取值,可以执行.findFirst()。get(),如Stream.of(5).map(test :: apply).findFirst()。get() – TechTrip 2014-09-18 22:55:50

0

尽管你的代码上述问题试图“超载变量”可以做到这一点。快速而丑陋的解决方案如下:

@SuppressWarnings("unchecked") 
public static <T> T addOrConcat(T x){ 

    if (x instanceof String){ 
     String ret = x.toString(); 
     return (T)(ret + ret); 
    } else if (x instanceof Integer){ 
     Integer ret = (Integer)x + (Integer)x; 
     return (T)(ret); 
    } 
    return null; 
} 

public static void main(String[] args) { 
    UnaryOperator<Object> test = x -> addOrConcat(x);  
    System.out.println(test.apply(Integer.valueOf(5))); 
    System.out.println(test.apply("5")); 
} 

输出将如下所示:

假以时日,我认为人们可以想出一些更有效的,更安全和直观。

2

在测试驱动开发的荣誉,我就可以把我的整个JUnit测试:

@Test 
public void shouldWork() { 
    UnaryOperator<Object> test = x -> { 
     if (x instanceof Integer) { 
      int intValue = (Integer) x; 
      return intValue + intValue; 
     } 
     return x.toString() + x.toString(); 
    }; 
    Assert.assertEquals(10, test.apply(5)); 
    Assert.assertEquals("55", test.apply("5")); 
} 

这是问题是一种面向对象编程和函数式编程的碰撞。

1

你不能,而问题是类型擦除。

您将需要一个单一的对象,既是Function<Integer, Integer>Function<String, String>,所以它有两个apply方法:

class MyFunc implements Function<Integer, Integer>, Function<String, String> { 
    public Integer apply(Integer v) { return x + x; } 
    public String apply(String v) { return x + x; } 
} 

然而,Java编译器不可能编译这是因为字节码不具备泛型的概念,所以这两个接口将是相同的,难以区分的。