2014-09-18 54 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編譯器不可能編譯這是因爲字節碼不具備泛型的概念,所以這兩個接口將是相同的,難以區分的。