2015-11-06 108 views
8

我期待在Java中創建特定類型的接口(儘管這適用於常規類)。這個接口需要包含一些方法,比如invoke;它將根據提供的泛型類型參數使用不同數量的參數進行調用。在Java中,我可以指定任何數量的泛型類型參數嗎?

舉個例子:

public interface Foo<T...> { 
    public void invoke(T... args); 
} 

// In some other class 
public static Foo<Float, String, Integer> bar = new Foo<Float, String, Integer>() { 
    @Override 
    public void invoke(Float arg1, String arg2, Integer arg3) { 
     // Do whatever 
    } 
}; 

爲了解釋,簡單地說,這到底是怎麼被使用(並提供一定的上下文中),考慮一類Delegator:類需要不同數量的泛型類型,並有一個方法 - invoke,帶有這些參數類型。該方法將其參數傳遞給列表中的對象:IDelegate的實例,該實例採用相同的通用類型。這允許Delegator在幾個委託方法(在IDelegate內定義)之間進行選擇,而不必爲每個特定的參數類型列表創建新的類。

是否有類似的東西可用?我已經閱讀了C++中的variadic templates,但在Java中找不到類似的東西。有這樣的東西嗎?如果不是,那麼模擬相同數據模型的最簡潔方法是什麼?

回答

4

是否有類似的東西可用?我已經閱讀了C++中的可變參數模板 ,但在Java中找不到任何類似的東西。是否有這樣的東西 ?

不,該功能在Java中不可用。

2

不,沒有這樣的東西直接可用。但是,如果您使用的是庫Tuple類,您可以通過只使得界面

interface Foo<T> { 
    void invoke(T t); 
} 

模擬它(這個接口是基本相同Consumer<T>

然後,你可以例如做

Foo<Tuple<String, Integer, Date, Long>> foo = new Foo<>() { 
    ... 
} 

對於每個參數數量,您需要單獨的Tuple類型。如果你有4個參數的Tuple類,但是5個沒有,你可以通過使用Pair類擠壓一個額外的參數。

Foo<Tuple<String, Integer, Date, Pair<Long, BigDecimal>>> foo = ... 

通過以這種方式嵌套元組類型,您可以獲得無限數量的參數。但是,這些解決方法非常難看,我不會使用它們。

+0

說得那樣:'Pair '就足夠了。但是由於沒有人想要一對'整數,一對<字符串,一對<字節,一對,所以像這樣的東西通常以不同的方式解決。要麼完全放棄類型安全,要麼使用像http://www.javatuples.org/這樣的庫。 – Marco13

2

鑑於您提供的上下文,我建議使用List作爲參數。如果這些參數具有某些共同點,則可以將列表限制爲<T extends CommonParrent>而不是使用List<Object>。如果沒有,您可能仍然想使用標記界面。

這裏是一個例子。

public class Main { 

    public static void main(String[] args) { 
     delegate(asList(new ChildOne(1), new ChildTwo(5), new ChildOne(15))); 
    } 

    private static <T extends Parent> void delegate(List<T> list) { 
     list.forEach(item -> { 
      switch (item.type) { 
       case ONE: delegateOne((ChildOne) item); break; 
       case TWO: delegateTwo((ChildTwo) item); break; 
       default: throw new UnsupportedOperationException("Type not supported: " + item.type); 
      } 
     }); 
    } 

    private static void delegateOne(ChildOne childOne) { 
     System.out.println("child one: x=" + childOne.x); 
    } 

    private static void delegateTwo(ChildTwo childTwo) { 
     System.out.println("child two: abc=" + childTwo.abc); 
    } 

} 

public class Parent { 
    public final Type type; 

    public Parent(Type type) { 
     this.type = type; 
    } 
} 

public enum Type { 
    ONE, TWO 
} 

public class ChildOne extends Parent { 
    public final int x; 

    public ChildOne(int x) { 
     super(Type.ONE); 
     this.x = x; 
    } 
} 

public class ChildTwo extends Parent { 
    public final int abc; 

    public ChildTwo(int abc) { 
     super(Type.TWO); 
     this.abc = abc; 
    } 
} 

這種解決方案的最大的缺陷就是孩子必須指定通過枚舉應該對應於switch語句中的類型轉換的類型,所以每當你改變這兩個地方之一,你必須記住改變另一個,因爲編譯器不會告訴你這一點。通過運行代碼並執行特定的分支,您只會發現這樣的錯誤,因此建議使用測試驅動開發。

相關問題