«1. Обзор

В этом кратком руководстве мы рассмотрим аннотацию @SafeVarargs.

2. Аннотация @SafeVarargs

В Java 5 появилась концепция varargs или параметра метода переменной длины, а также параметризованных типов.

Их объединение может вызвать у нас проблемы:

public static <T> T[] unsafe(T... elements) {
    return elements; // unsafe! don't ever return a parameterized varargs array
}

public static <T> T[] broken(T seed) {
    T[] plant = unsafe(seed, seed, seed); // broken! This will be an Object[] no matter what T is
    return plant;
}

public static void plant() {
   String[] plants = broken("seed"); // ClassCastException
}

Компилятору сложно подтвердить эти проблемы, поэтому он выдает предупреждения всякий раз, когда они объединяются, например, в случае небезопасного:

warning: [unchecked] Possible heap pollution from parameterized vararg type T
  public static <T> T[] unsafe(T... elements) {

~~ ~ Этот метод при неправильном использовании, как в случае с неработающим, загрязнит массив Object[] в куче вместо предполагаемого типа b.

Чтобы убрать это предупреждение, мы можем добавить аннотацию @SafeVarargs к конечным или статическим методам и конструкторам.

@SafeVarargs похож на @SupressWarnings тем, что позволяет нам объявить, что конкретное предупреждение компилятора является ложным срабатыванием. Как только мы убедимся, что наши действия безопасны, мы можем добавить эту аннотацию:

public class Machine<T> {
    private List<T> versions = new ArrayList<>();

    @SafeVarargs
    public final void safe(T... toAdd) {
        for (T version : toAdd) {
            versions.add(version);
        }
    }
}

Безопасное использование varargs само по себе является сложной концепцией. Для получения дополнительной информации у Джоша Блоха есть отличное объяснение в его книге «Эффективная Java».

3. Заключение

В этой быстрой статье мы увидели, как использовать аннотацию @SafeVarargs в Java.

Полный исходный код примеров можно найти на GitHub.