Упрощенный вызов метода Varargs в Java 7 - PullRequest
16 голосов
/ 22 октября 2011

В Java 7 у вас есть возможность поместить аннотацию @SafeVarargs, чтобы подавить предупреждение, которое вы получаете при компиляции метода с параметром varargs без переопределения. Предложение Project Coin предусматривает, что аннотация должна использоваться, когда метод гарантирует, что в массиве varargs хранятся только элементы того же типа, что и параметр varargs.

Что было бы примером небезопасного метода?

1 Ответ

21 голосов
/ 22 октября 2011

Например, foo() небезопасно, он может хранить не-T в массиве, вызывая проблему в [2]

<T extends List<?>> void foo(T... args)
{
    List<String>[] array2 = (List<String>[])args;
    array2[0] = a_list_of_string;
}

void test2()
{
    List<Integer>[] args = ...;   // [1]
    foo(args);
    Integer i = args[0].get(0);   // [2]
}

Помечая метод с помощью @SafeVarargs, вы обещаете компилятору, что не будете делать ничего подобного.


Но как, черт возьми, мы можем получить общий массив в [1] для начала? Java не позволяет создавать универсальные массивы!

Единственный санкционированный способ создания универсального массива - это вызов метода vararg

foo( list_int_1, list_int_2 )

тогда массив не доступен для вызывающей стороны, вызывающая сторона не может сделать [2] в любом случае, не имеет значения, как foo() портится с массивом.

Но затем вы думаете об этом, является бэкдором для создания универсального массива

@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
    return Arrays.copyOf(array, length);
}

List<String>[] array1 = newArray(10);

и литерал универсального массива

@SafeVarargs
static <E> E[] array(E... array)
{
    return array;
}

List<String>[] array2 = array( list1, list2 );

Итак, мы можем создать универсальный массив в конце концов ... Глупая Java, пытаясь помешать нам сделать это.

...