2012-02-16 64 views
5

以下Python剪掉不正是我的意思是:如何在Java中擴展參數?

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

def function(a, b, c): 
    print("%i :: %s :: %f" % (a,b,c)) 

a = 1 
b = "abc" 
c = 1.0 

function(a, b, c) 

list = [a, b, c] 

# This is what I am searching for in Java 
function(*(list)) 

所以我有一個列表類似的結構,我不知道有多少爭論了,但我知道它有參數的權數有正確的類型和格式。我想將它們傳遞給一個方法。所以我必須「擴大」這些論點。有人知道如何在Java中這樣做嗎?

+0

你也許好看[供](http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java)可變參數(http://docs.oracle.com /javase/1.5.0/docs/guide/language/varargs.html)? – 2012-02-16 10:27:22

+0

定義「展開」?從你的例子中不清楚這意味着什麼。 – Tudor 2012-02-16 10:30:28

+0

如果你只是想使用類似''%操作,您可以使用'Formatter'類,如我的回答如下。 – 2012-02-16 10:39:18

回答

5

Java沒有這種功能,因爲作爲一種靜態的強類型語言,一種方法採用統一類型的值的集合並不常見,這些統一類型的值都可以存儲在某個組合對象(數組,列表等)中)。 Python沒有這個問題,因爲一切都是動態類型的。您可以通過定義一個幫助器方法在Java中執行此操作,該方法在保存所有參數時採用單個對象,然後在調用實際方法時擴展它們。

希望這會有所幫助!

1

你不能。在Java中,方法參數在編譯時被檢查,並且由於數組的內容僅在運行時被定義,所以這種檢查是不可能的。

您最接近的解決方案是有一個方法將數組作爲參數,並最終擴展參數以調用目標方法。

2

你可以用Object...這樣的聲明可選參數,你可以用傳入的任意號碼,然後投下他們每個人所需要的類型:

public void method1(String p1, Integer p2) { 
} 

public void method2(Object... params) { 
    method1((String)params[0], (Integer)params[1]; 
} 

你可以叫method2爲:

method2("abc", 1); 

當然,這個例子有點多餘,因爲你可以直接調用method1,但這不是我想說明的。 :)

0

你可以這樣做:

import java.util.Formatter; 

// ... 

StringBuilder target = new StringBuilder(); 
Formatter formatter = new Formatter(target); 

List<Integer> integers = new ArrayList<Integer>(); 
integers.add(1); 
integers.add(2); 
integers.add(3); 

formatter.format("%d %d %d", integers.toArray()); 
System.out.println(target.toString()); 

編輯:Javadoc for java.util.Formatter

0

我認爲這樣做同樣的事情,你有類似的語法初始代碼...

public class MultiArgs { 

    public static void main(String[] args) { 
     int a = 1; 
     String b = "abc"; 
     double c = 1.0; 
     List<?> list = Arrays.asList(a, b, c); 

     System.out.println(function(a, b, c)); // 1 :: abc :: 1.000000 
     System.out.println(function(list.toArray())); // 1 :: abc :: 1.000000 
    } 

    private static <T extends Object> String function(T... objects) { 
     return String.format("%d :: %s :: %f", objects); 
    } 
} 
0

不建議這樣做(正如templatetypedef的答案所指出的,這是強類型語言的一種非常罕見的模式),但是你可以ld使用反射來做你想做的事。

SomeType foo = //obtained from elsewhere 
List<?> args = //obtained from somewhere else 

//this bit obtains the method handle 
Method theMethod = null; 
for (Method m : foo.getClass().getMethods()) { 
    if (m.getName().equals("theMethodIWant") { 
     theMethod = m; 
     break; 
    } 
} 

theMethod.invoke(foo, args.toArray()); //this is the line that does the magic 

一些相當嚴重的警告:

  • 反射相比可直接調用有顯著的性能影響 - 遠遠超過像Python這樣的動態語言。這可能或可能不重要。如有疑問,請測量。

  • ,其獲得方法處理將導致空指針,如果使用該名稱的方法沒有找到

  • 的參數列表必須具有完全相同的觀點的權利數量,用正確的類型塊。您有責任在其他地方驗證此事。這比動態語言更難,因爲運行時會爲你做更少(如果有的話)類型的強制。

  • method.invoke()可以拋出一些例子(IllegalAccessException,IllegalArgumentException,InvocationTargetException等),這個例子忽略。你必須捕捉和處理這些錯誤適當

  • 如果被調用的方法是不公開的,你必須做的比這更多的工作來調用它。

  • 這個例子甚至沒有嘗試處理你有一個重載方法的情況。兩個名爲「theMethodIWant」的方法具有不同的參數列表,需要不同的方法來獲取方法句柄。

總而言之,如果可能的話,我會建議不要使用反射。