Решите "непроверенное предупреждение" в Java, избегая @supressWarning

Это попытка улучшить мой код вопроса. О дженериках и непроверенном предупреждении; Я знаю о @suppresswarning аннотаций. Вопрос в том, что я должен кодировать, чтобы подавить его. Возьми, пожалуйста, следующий код.

public class NumericBox<T extends Number> implements Box<T> {

    private T element;


    public NumericBox(T element) {
        this.element = element;
    }

    @Override public T getElement() {
        return element;
    }

    public T insert(Number newElement) {
        T oldElement = this.element;
        this.element = (T) newElement; // warning("unchecked")
        return oldElement;
    }

}

Какой способ кодирования это сделать (не аннотации). В документах, которые я нашел, термин "непроверенный" означает, что у компилятора недостаточно информации о типе, чтобы выполнить все проверки типов, необходимые для обеспечения безопасности типов. Но не понимаю. Мне кажется, это нормально

void foo(Number n) {
    Short asShort = (Short) n; //OK
    T  asTypeWhichExtendsNumber = (T) n; // warning
}

Extra. если я хочу добавить пустой конструктор, есть ли способ сохранить "ноль" в элементе?

NumeircBox<Short> o = new NumericBox<>(); // expectes 0 in the element

2 ответа

Решение

Давайте посмотрим на рассматриваемый код, ваш class объявление:

public class NumericBox<T extends Number> implements Box<T>

Итак, у нас есть какой-то тип T тот extends Number, Это может быть Long, Integer и т.д. Но некоторые конкретные и определенные во время компиляции типа.

Теперь у вас есть метод:

public T insert(Number newElement) {
    T oldElement = this.element;
    this.element = (T) newElement;
    return oldElement;
}

Что занимает некоторое Number любого типа - ни специфического, ни определенного во время компиляции, и вы приводите его в T, Это ClassCastException жду, чтобы случиться.

final NumericBox<BigDecimal> box = new NumericBox<>();
box.insert(3);
final BigDecimal val = box.getElement();  <-- OOPS!

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

Итак, чтобы решить вашу проблему, измените код на:

public T insert(T newElement) {
    T oldElement = this.element;
    this.element = (T) newElement;
    return oldElement;
}

Так как генерики стираются во время компиляции, на самом деле нет никакого способа исправить этот хак. Если вы хотите гарантировать безопасность типов во время выполнения, вам нужно изменить подпись. Если вы хотите взять "любой старый Number "Тогда вам придется иметь дело с последствиями.

Объявите метод "insert" как принимающий параметр типа T, а не Number. Прямо сейчас вызывающий может передать любой номер, а не только тот, который соответствует параметру типа T вашего класса, и вы получите ClassCastException во время выполнения, если тип не совпадает.

Другие вопросы по тегам