2011-06-12 80 views
8

我試圖寫一個Java功能,可以與任意數量的整數和字符串的被稱爲原型:方法原型中可變參數的多個對象類型?

myMethod(1, 2, 3, "Hello", "World"); // Valid call 
myMethod(4, "foo", "bar", "foobar"); // Valid call 

理想情況下,我想在整數和字符串以任何順序給予(和可能混合):

myMethod(1, "Hello", 2, "World", 3); // Valid call 

我想使用可變參數,但在原型中只能有一個。另一個想法我已經是使用下面的原型:

public void myMethod(Object ... objs) { [...] } 

...但我覺得應該有一個編譯錯誤的情況下,它被稱爲比預期的類型以外的東西。當然,可以執行運行時檢查(instanceof),但那不會是一個非常優雅的解決方案,對嗎?

你會怎麼做?

回答

5

Java編程語言無法讓它正常工作,以便您可以傳遞任意數量的字符串和整數,並且當您傳遞除字符串或整數之外的其他字符時,編譯器會報錯。

+0

這就是我所害怕的。謝謝,我會訴諸於Object varargs。 – executifs 2011-06-12 13:17:58

3

沒有辦法使用泛型來匹配兩種類型,如

public <T extends String | Integer> void myMethod(T... objs); // You can't do this 
+0

太糟糕了(雖然這將是一個很好的功能 – executifs 2011-06-12 13:20:09

+3

不是這樣會使泛型沒有意義,代碼會隨機出現ClassCastExceptions; – Jeshurun 2013-06-28 03:41:51

+1

我想知道是否有人盲目複製/粘貼這段代碼,然後在沒有的時候感到沮喪 – 2016-05-15 05:30:37

6

如果你希望它是類型安全的,我會去這個:

public myMethod(Thing<?>... thing) { ... } 

然後創建你的事情類:

public interface Thing<T> { 
    public T value(); 
} 

public class IntThing implements Thing<Integer> { 
    private final int value; 

    public IntThing(int value) { 
     this.value = value; 
    } 

    public Integer value() { 
     return value; 
    } 
} 

我會讓它想你想象如何寫StringThing。顯然,使用比「事」更好的名字,但我不能幫你。

然後,您可以讓兩個靜態方法:

public static Thing<Integer> thing(int value) { 
    return new IntThing(value); 
} 

public static Thing<String> thing(String value) { 
    return new StringThing(value); 
} 

然後你包裹在呼叫每個對象thing

myMethod(thing(1), thing(2), thing(3), thing("Hello"), thing("World")); 

凌亂?對。不幸的是,Java沒有像其他語言一樣隱藏這些東西的能力。斯卡拉的隱含defs會幫助你,但是伴隨着其他一系列問題。就我個人而言,我會用instanceof檢查,但這一個將確保您的代碼在編譯時是安全的。

+0

謝謝,這將起作用,但'Thing'包裝可能會讓API用戶感到困惑,讓他們在不考慮它的工作原理的情況下調用myMethod對我來說比打字更重要,安全 – executifs 2011-06-12 13:29:00

+0

在這種情況下,你的可變參數可能是最好的。 – 2011-06-12 16:00:09

1

您所描述的問題的唯一可能的解決方案是已經聲明的方法,其中函數採用Object類型的可變參數參數。這是由於Java中的限制,在方法簽名中只能有一個可變參數,並且它必須是最後一個參數。

很難說如果不知道你打算做什麼的細節,可以選擇一個優雅的解決方案。

1

(解決方法)

添加到庫:

package mylib; 

public class Lang { 
    public static <T> T[] varargs (T...ts) { 
     return ts; 
    } 
} 

在你的程序:

package myprog; 

import static mylib.Lang.*; 

public class MyProg { 

    public static void testfunc (Integer[] ints, String[] strs) { 

     for (int i : ints) 
      System.out.println(i); 

     for (String s : strs) 
      System.out.println(s); 
    } 

    public static void main (String[] args) { 
     testfunc(
      varargs(1,2,3), 
      varargs("Sophia", "Jacob") 
     ); 
    } 
} 

(打破許多編碼樣式規則)

0

語法允許

public class Foo<T extends Number & List> { 
    ... 
} 

類型變量T允許相同類型的子類型爲NumberList的類型(例如,實現多個接口的類型)。