Вопрос

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

@SuppressWarnings("unchecked")

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

Предупреждения о подавлении

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

Аннотации

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

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

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

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

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

   Collections.reverse(list);
   return list;
}

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

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

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

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

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

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

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

В 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

Ан 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;
}

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

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

Пример:

@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;

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

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

Предупреждение, с помощью которого компилятор указывает, что он не может обеспечить безопасность типов.Термин "непроверенное" предупреждение вводит в заблуждение.Это никоим образом не означает, что предупреждение снято.Термин "непроверенный" относится к тому факту, что компилятор и система выполнения не располагают достаточной информацией о типе для выполнения всех проверок типов, которые были бы необходимы для обеспечения безопасности типов.В этом смысле определенные операции являются "непроверенными".

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

Пример (непроверенного предупреждения в сочетании с необработанными типами):

TreeSet set = new TreeSet(); 
set.add("abc");        // unchecked warning 
set.remove("abc");
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.TreeSet 
               set.add("abc");  
                      ^

Когда вызывается метод add, компилятор не знает, безопасно ли добавлять объект String в коллекцию.Если набор деревьев представляет собой коллекцию, содержащую строку s (или ее супертип), то это было бы безопасно.Но из информации о типе, предоставленной необработанным набором типов TreeSet, компилятор не может определить.Следовательно, вызов потенциально небезопасен и выдается предупреждение "непроверено".

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

Пример (непроверенного предупреждения в сочетании с приведением к параметризованному типу или переменной типа):

  class Wrapper<T> { 
  private T wrapped ; 
  public Wrapper (T arg) {wrapped = arg;} 
  ... 
  public Wrapper <T> clone() { 
    Wrapper<T> clon = null; 
     try {  
       clon = (Wrapper<T>) super.clone(); // unchecked warning 
     } catch (CloneNotSupportedException e) {  
       throw new InternalError();  
     } 
     try {  
       Class<?> clzz = this.wrapped.getClass(); 
       Method   meth = clzz.getMethod("clone", new Class[0]); 
       Object   dupl = meth.invoke(this.wrapped, new Object[0]); 
       clon.wrapped = (T) dupl; // unchecked warning 
     } catch (Exception e) {} 
     return clon; 
  } 
} 
warning: [unchecked] unchecked cast 
found   : java.lang.Object 
required: Wrapper <T> 
                  clon = ( Wrapper <T>)super.clone();  
                                                ^ 
warning: [unchecked] unchecked cast 
found   : java.lang.Object 
required: T 
                  clon. wrapped = (T)dupl;

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

В приведенном примере приведение к оболочке будет проверять, является ли объект, возвращаемый из super.clone, оболочкой, а не является ли это оболочкой с определенным типом элементов.Аналогично, приведения к параметру типа T преобразуются в type Object во время выполнения и, вероятно, полностью оптимизируются.Из-за удаления типа система среды выполнения не может выполнять более полезные проверки типов во время выполнения.

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

Пожалуйста, обратитесь: Что такое "непроверенное" предупреждение?

Аннотация @SuppressWarnings является одной из трех встроенных аннотаций, доступных в JDK и добавленных вместе с @Override и @Deprecated в Java 1.5.

@SuppressWarnings предписывает компилятору игнорировать или подавлять указанное предупреждение компилятора в аннотируемом элементе и всех программных элементах внутри этого элемента.Например, если класс аннотирован для подавления определенного предупреждения, то предупреждение, сгенерированное в методе внутри этого класса, также будет отделено.

Возможно, вы видели @SuppressWarnings("непроверенный") и @SuppressWarnings("последовательный"), два наиболее популярных примера аннотации @SuppressWarnings.Первое используется для подавления предупреждения, генерируемого из-за непроверенного приведения, в то время как более позднее предупреждение используется для напоминания о добавлении serialVersionUID в сериализуемый класс.

Подробнее: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top