2014-08-30 25 views
20

Mam rodzaju metody util przekształcić varargs danego typu do tablicy tego typu - wygląda to tak:Czy to korzystanie z varargs jest bezpieczne?

public K[] array(K... ks) { 
    return ks; 
} 

Sprawa stosowanie jest tak, że zamiast definiowania tablicę podczas wywoływania metody co wymaga tablicy, możesz po prostu zrobić tablicę (val1, val2, val3).

Jednak IntelliJ daje mi ostrzeżenia o zanieczyszczeniu sterty. Rozumiem, co to oznacza w pewnym stopniu, ale nie mam dużego doświadczenia ze specyfiką - chciałbym wiedzieć, czy mogę dodać @SafeVarargs i czy ta metoda jest rzeczywiście bezpieczna.

IntelliJ mówi:

Problem streszczenie Możliwe zanieczyszczenie sterty z parametryzowanego typu vararg na linii 249

rozdzielczości Problem Bądź ostateczna i opisywanie jak @SafeVarargs

K jest zadeklarowana jako typ parametru klasy, wraz z V.

+13

IMO nie trzeba takiej metody, wystarczy użyć 'Cokolwiek [] = {whateverArray val1, wart2, val3, ...};' –

+0

Czy możesz podać dokładnych * * szczegóły ostrzeżenia zanieczyszczenia kupa? I gdzie jest zadeklarowany parametr typu "K"? –

+0

@ Luiggi, tak, ale to narzędzie. 'K [] keys = {key1, key2, key3}; object.method (keys); 'vs' object.method (array (key1, key2, key3)); '- drugi jest o wiele łatwiejszy do napisania, zwłaszcza gdy robisz to dużo. – DziNeIT

Odpowiedz

24

Nie, to nie jest bezpieczna - jeśli wywołana z innej metody, która używa generycznych. Oto pełna przykładów, które wygląda porządku, ale zgłasza wyjątek:

class Utility<K> { 
    public K[] array(K... ks) { 
     return ks; 
    } 

    public K[] otherMethod(K k1, K k2) { 
     return array(k1, k2); 
    } 
}  

class Test { 
    public static void main(String[] args) throws Exception { 
     Utility<String> util = new Utility<String>(); 
     // Bang! 
     String[] array = util.otherMethod("foo", "bar"); 
    } 
} 

Gdy kompilator tworzy kodu bajtowego dla otherMethod, to nie można utworzyć tablicę odpowiedniego rodzaju przejść do array, ponieważ nie zna typu K. Ze względu na wymazywanie typu, po prostu tworzy wartość Object[]. Tak więc w main istnieje ukryty rzut od wyniku otherMethod do String[] ... i to się nie powiedzie w czasie wykonywania.

Jeśli zadzwonisz array bezpośrednio z kodu, który naprawdę zna rodzaje argumentów, to jest w porządku, ponieważ domyślnie tworzone tablica będzie odpowiedni rodzaj.

+0

dziękuję. Dopóki jest to jedyna (w granicach rozsądku) sytuacja, która mogłaby spowodować problem, powinno być w porządku dla tego, co robię. – DziNeIT

+3

Zachowaj ostrożność tutaj, @DziNeIT. Jeśli to tylko szaleństwo i jesteś jedyną osobą używającą tego kodu, to śmiało. Wiem, jaka byłaby moja opinia, gdybym jednak spotkała się z czymś takim. To dobre pytanie z równie dobrą odpowiedzią. :) – TEK

0

Możesz po prostu powiedzieć swojej metody konwersji do odpowiedniej tablicy. Jednym ze sposobów, jakie znalazłem, było przekazanie tablicy do metody za pomocą zmiennych, a następnie skopiowanie do niej.

public K[] otherMethod(K[] parent, K k1, K k2) { 
    List<K> list = new ArrayList<K>(); 
    Collections.addAll(list, array(k1, k2)); 
    list.toArray(parent); 
    return parent; 
} 

Teraz wyjście zależy od metody Collections.toArray(), która zwraca null, jeśli nie ma w tablicy wystarczająco dużo miejsca, lub jeśli istnieje dodatkowa przestrzeń niewykorzystane wartości będzie null.

class Test { 
    public static void main(String[] args) throws Exception { 
     Utility<String> util = new Utility<String>(); 
     String[] array = util.array("one", "two", "three"); 
     array = util.otherMethod(array, "x", "y"); 
     printArr(array); // prints: x y null 

     Utility<Integer> util2 = new Utility<Integer>(); 
     Integer[] intarray = util2.otherMethod(new Integer[1], 1, 2); 
     printArr(intarray); // prints: null 
     Integer[] intarray = util2.otherMethod(new Integer[2], 1, 2); 
     printArr(intarray); // prints: 1 2 
    } 

    static void printArr(Object[] objArr) { 
     for (Object o:objArr) System.out.print(o+"\t"); 
    } 
} 
Powiązane problemy