Что такое SuppressWarnings ("unchecked") в Java?

когда-то при просмотре кода я вижу, что многие методы указывают аннотацию:

@SuppressWarnings("unchecked")

что это значит?

9 ответов


иногда Java generics просто не позволяет вам делать то, что вы хотите, и вам нужно эффективно сказать компилятору, что вы действительно делаете будет быть законным во время выполнения.

Я обычно нахожу это боль, когда я издеваюсь над общим интерфейсом,но есть и другие примеры. Обычно стоит попытаться выработать способ избежать предупреждения, а не подавлять его (Java Generics FAQ помогает здесь), но иногда даже если это is возможно, он изгибает код из формы настолько, что подавление предупреждения аккуратнее. Всегда добавляйте пояснительный комментарий в этом случае!

в одном и том же FAQ по дженерикам есть несколько разделов по этой теме, начиная с "что такое" непроверенное " предупреждение?" - это стоит прочитать.


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

вы можете прочитать больше об этой конкретной аннотации здесь:

SuppressWarnings

кроме того, Oracle предоставляет некоторую документацию по использование аннотаций здесь:

аннотации

как они выразились,

"предупреждение" unchecked " может возникнуть при взаимодействии с устаревшим кодом, написанным до появления дженериков (обсуждается в уроке под названием дженерики)."


это также может означать, что текущая версия системы типов Java недостаточно хороша для вашего случая. Их было несколько!--2-->предложения JSR / hacks, чтобы исправить это: введите токены,Супер Токены Типа, класс.отбрасывать.)(

Если вам действительно нужно это подавление, сузьте его как можно больше (например, не помещайте его в сам класс или в длинный метод). Пример:

public List<String> getALegacyListReversed() {
   @SuppressWarnings("unchecked") List<String> list =
       (List<String>)legacyLibrary.getStringList();

   Collections.reverse(list);
   return list;
}

на SuppressWarning аннотация используется для подавления предупреждений компилятора для аннотированного элемента. В частности,unchecked категория позволяет подавлять предупреждения компилятора, генерируемые в результате непроверенных приведений типов.


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

метод обслуживания JPA например:

@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
    Query query = entitymanager.createQuery("SELECT u FROM User u");
    return (List<User>)query.getResultList();
}

Если бы я не анотировал @SuppressWarnings ("unchecked") здесь, у него была бы проблема с line, где я хочу вернуть свой ResultList.

в ярлыке тип-безопасность означает: программа считается типобезопасной, если она компилируется без ошибок и предупреждений и не вызывает никаких неожиданных ClassCastException s на во время выполнения.

Я строю на http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html


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

пример:

@SuppressWarnings("unchecked")
public List<ReservationMealPlan> retreiveMealPlan() {
     List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>();
    TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance);
    list = testMenuService.getMeal(reservationMealPlan);
    return list;
 }

один трюк-создать интерфейс, который расширяет общий базовый интерфейс...

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}

затем вы можете проверить его с помощью instanceof перед приведением...

Object obj = context.getAttribute(FUTURES);
if (!(obj instanceof LoadFutures)) {
    String format = "Servlet context attribute \"%s\" is not of type "
            + "LoadFutures. Its type is %s.";
    String msg = String.format(format, FUTURES, obj.getClass());
    throw new RuntimeException(msg);
}
return (LoadFutures) obj;

в Java дженерики реализуются с помощью стирания типа. Например, следующий код.

List<String> hello = List.of("a", "b");
String example = hello.get(0);

компилируется следующим образом.

List hello = List.of("a", "b");
String example = (String) hello.get(0);

и List.of определяется как.

static <E> List<E> of(E e1, E e2);

, которая после стирания типа становится.

static List of(Object e1, Object e2);

компилятор понятия не имеет, что такое универсальные типы во время выполнения, поэтому, если вы напишете что-то вроде этого.

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;

виртуальная машина Java понятия не имеет, какие общие типы при запуске программы, так что это компилируется и запускается, как для виртуальной машины Java, это приведение к List type (это единственное, что он может проверить, поэтому он проверяет только это).

но теперь добавьте эту строку.

Integer hello = actualList.get(0);

и JVM бросит неожиданный ClassCastException, поскольку компилятор Java вставил неявное приведение.

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer

An unchecked предупреждение сообщает программисту, что приведение может привести к тому, что программа выдаст исключение где-то еще. Подавление предупреждение с @SuppressWarnings("unchecked") сообщает компилятору, что программист считает код безопасным и не вызовет неожиданных исключений.

зачем вы хотите это сделать? Система типов Java недостаточно хороша для представления всех возможных шаблонов использования типов. Иногда вы можете знать, что приведение безопасно, но Java не предоставляет способ сказать это-скрыть предупреждения, подобные этому,@SupressWarnings("unchecked") может использоваться, чтобы программист мог сосредоточиться на реальных предупреждениях. Например, Optional.empty() возвращает синглтон в избегайте выделения пустых optionals, которые не хранят значение.

private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

это приведение безопасно, так как значение, хранящееся в пустом необязательном, не может быть извлечено, поэтому нет риска непредвиденных исключений приведения класса.


насколько я знаю, сейчас это связано с подавлением предупреждений о дженериках; дженерики-это новая конструкция программирования, не поддерживаемая в версиях JDK ранее JDK 5, поэтому любые сочетания старых конструкций с новыми могут привести к неожиданным результатам.

компилятор предупреждает об этом программиста, но если программист уже знает, они могут отключить эти страшные предупреждения с помощью SuppressWarnings.