2017-02-01 64 views
2

有沒有什麼辦法可以引用Java 8中的一組方法,這會改變它們的簽名方式?Java 8中的方法引用:是否支持重載?

更確切地說,我想這個代碼工作:

public class OverloadingMethodRef 
{ 
    public static void foo (int x) { 
     System.out.println ("An integer: " + x); 
    } 

    public static void foo (String x) { 
     System.out.println ("A String: " + x); 
    } 

    /** 
    * I want it to work without this 
    */ 
// public static void foo (Object x) { 
//  if (x instanceof Integer) foo ((int) x); else foo ((String) x); 
// } 

    public static void main (String[] args) 
    { 
     // Compile error, it wants a precise reference to one of them 
     Consumer<Object> c = PolymorphicMethodRef::foo; 
     foo ("bla"); // despite it could get it 
     foo (1); // and here too 
    } 
} 

我不能添加public static void foo (Object x),因爲我有很多的方法來傳遞給另一個方法,我不想寫包裝。到目前爲止,我只能通過反射(它可以接收param.getClass())來完成此操作,但我必須調用的方法具有不同的參數(> = 1),每次需要將它們放入數組中時,再將它們的類型放入另一箇中。

+3

支持多態。也沒有 - 這不是多態,這是**重載**。不,沒有 - Java編程方法在編譯時調用特定的方法重載。 –

+0

Whops!是的,我的意思是超載,我解決了這個問題,謝謝。 – zakmck

+1

確實不可能獲得方法引用,就好像它指向重載方法一樣。你可以做的最好的方法是添加另一種方法,如void foo(Object x),並讓用戶退出,但它仍然會始終調用該方法(使用Object參數),永遠不會解析其他任何東西。 –

回答

5

方法引用支持使用與普通方法調用相同的規則進行重載。當你有一個Consumer<Object>,你可以通過任意Object情況下,其accept方法,即你可以寫

Consumer<Object> c = /* some expression producing it*/; 
c.accept(new JButton()); 
// or just 
c.accept(new Object()); 

因爲你不能寫

foo(new JButton()); 
// or 
foo(new Object()); 

當你只有一個foo(int)foo(String),它也不可能寫出

Consumer<Object> c = OverloadingMethodRef::foo; 

這將構建一個Consumer假裝接受任意Object實例。

如果你願意接受反射的開銷,你可以使用

Consumer<Object> c=o -> { 
    try { 
     new Statement(OverloadingMethodRef.class, "foo", new Object[]{o}).execute(); 
    } catch (Exception ex) { 
     throw new RuntimeException(ex); 
    } 
}; 
c.accept(42); 
c.accept("bla"); 

(這是指java.beans.Statement

當然,這可以用一個不支持的參數被調用時,在運行時失敗類型。

+0

謝謝@Holger。在實踐中,這是從Java中缺少的:-)我知道它符合靜態類型檢查,但仍然不是很好(接受任意對象,在運行時綁定並在編譯時提出警告對我來說會更好)。 Re:反射,我使用'org.apache.commons.lang3.reflect.MethodUtils',更簡單的語法。 – zakmck