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


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

@SuppressWarnings("unchecked")

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

9 371

9 ответов:

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

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

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

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

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

SuppressWarnings

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

аннотации

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

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

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

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

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") здесь, у него была бы проблема с линией, где я хочу вернуть свой ResultList.

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

Я строю на 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 тип (это единственное, что он может проверить, поэтому он проверяет только это).

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

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() возвращает синглтон в избегайте выделения пустых опционов, которые не хранят значение.

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.