我似乎無法使其工作。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」?
我似乎無法使其工作。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」?
test
是一個變量,它不是一個方法。你不能重載一個變量。
您可能會嘗試使用兩個方法簽名創建接口,但結果不會是功能接口,並且您無法使用lambda實現它。我們再次失敗。
所以,無論如何,沒有辦法做'test.apply(5)'和'test.apply(「5」)'並得到我描述的行爲在問題中? – SGr 2014-09-18 21:20:34
你可以,但絕對不能使用lambda來實現'test :: apply'。自定義界面的行人執行將是唯一的方法。 – 2014-09-18 21:21:04
簡而言之:你不能。
你在做什麼不是超載。它創建了兩個不同的實例,其中包含衝突名稱的界面。
這相當於做:
int a = 1;
int a = 2;
在同一範圍內,同樣是非法的。
超載會發生,如果你能在Function
接口兩個apply
定義 - 一個以String
參數,一個以int
。你不能(輕易地)修改java中的現有接口。
您不能有一個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);
}
儘管你的代碼上述問題試圖「超載變量」可以做到這一點。快速而醜陋的解決方案如下:
@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"));
}
輸出將如下所示:
假以時日,我認爲人們可以想出一些更有效的,更安全和直觀。
在測試驅動開發的榮譽,我就可以把我的整個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"));
}
這是問題是一種面向對象編程和函數式編程的碰撞。
你不能,而問題是類型擦除。
您將需要一個單一的對象,既是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編譯器不可能編譯這是因爲字節碼不具備泛型的概念,所以這兩個接口將是相同的,難以區分的。
而不是使用函數你可以簡寫爲UnaryOperator –
TechTrip
2014-09-18 22:05:46