2012-02-16 7 views
5

Poniższy Python snipped robi dokładnie to, co mam na myśli:Jak mogę rozwinąć argumenty w Javie?

#!/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)) 

Mam więc jedną listę podobną strukturę i nie wiem, jak wiele argumentów ma, ale wiem, że ma odpowiednią liczbę argumentów z właściwym typem i formatem. I chcę przekazać je do metody. Muszę więc "rozszerzyć" te argumenty. Czy ktoś wie, jak to zrobić w Javie?

+0

Być może szukasz [na] (http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java) [varargs] (http://docs.oracle.com /javase/1.5.0/docs/guide/language/varargs.html)? –

+0

Zdefiniuj "rozwiń"? Z twojego przykładu nie wynika jasno, co to oznacza. – Tudor

+0

Jeśli chcesz po prostu użyć czegoś takiego jak operator '%', możesz użyć klasy 'Formatter', tak jak w mojej odpowiedzi poniżej. –

Odpowiedz

5

Java nie ma tego obiektu, ponieważ jako statycznie napisany język rzadko spotyka się metodę pobierania zbioru wartości jednolitego typu, który może być przechowywany w jakimś złożonym obiekcie (tablica, lista itd. .). Python nie ma tego problemu, ponieważ wszystko jest napisane dynamicznie. Możesz to zrobić w Javie, definiując metodę helpera, która pobiera pojedynczy obiekt podczas przechowywania wszystkich parametrów, a następnie rozwija je w wywołaniu prawdziwej metody.

Mam nadzieję, że to pomoże!

1

Nie możesz. W Javie parametry metody są sprawdzane w czasie kompilacji, a ponieważ zawartość tablicy jest zdefiniowana tylko w czasie wykonywania, kontrola ta byłaby niemożliwa.

Twoje najbliższe rozwiązanie polega na tym, że metoda przyjmuje tablicę jako parametr, a docelowo rozszerza argumenty, aby nawiązać połączenie z docelową metodą.

2

Można zadeklarować parametry opcjonalne z Object... taki sposób, że można przekazać dowolną liczbę argumentów, a następnie rzucił każdy z nich do wymaganego typu:

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

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

można zadzwonić method2 jak:

method2("abc", 1); 

Oczywiście ten przykład jest nieco zbędny, ponieważ można bezpośrednio zadzwonić pod numer method1, ale nie jest to tym, co chciałem zilustrować. :)

0

Można to zrobić:

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()); 

Edit:Javadoc for java.util.Formatter

0

myślę, że to nie to samo, co początkowego kodu z podobnej składni ...

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

To nie jest zalecane (jak zauważa odpowiedź templatetypedef, jest to bardzo nietypowy wzorzec dla języka o silnym typie), ale Zróbmy to, co chcesz, za pomocą refleksji.

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 

Niektóre dość poważne zastrzeżenia:

  • Odbicie może mieć znaczący wpływ na wydajność w porównaniu do bezpośredniej rozmowy - o wiele bardziej niż w dynamicznym językiem jak pyton. To może, ale nie musi mieć znaczenia. W razie wątpliwości zmierzyć.

  • Blok że uzyskuje uchwyt metoda spowoduje null pointer jeśli metoda o tej nazwie nie zostanie znaleziony

  • Lista argumentów musi mieć dokładnie właściwą liczbę argumentów, z prawej Typ . Jesteś odpowiedzialny za weryfikację tego w innym miejscu. Jest to trudniejsze, niż byłoby to w przypadku dynamicznego języka, ponieważ środowisko wykonawcze zrobi dla ciebie dużo mniej (jeśli w ogóle) jakiegoś rodzaju wymuszenie.

  • Metoda.invoke() może wyrzucać wiele wyjątków (IllegalAccessException, IllegalArgumentException, InvocationTargetException, itp.), Które ten przykład ignoruje. Będziesz musiał złapać i poradzić sobie z tymi błędami, odpowiednio

  • jeśli wywoływana metoda nie jest publiczna, będziesz musiał wykonać jeszcze więcej pracy niż to, aby ją wywołać.

  • Ten przykład nie próbuje nawet uporać się z przypadkiem, w którym masz przeciążoną metodę. Dwie metody o nazwie "theMethodIWant" z różnymi listami argumentów będą wymagały innego podejścia, aby uzyskać uchwyt metody.

Podsumowując, nie zaleca się używania refleksji, jeśli to możliwe.