Що таке SuppressWarnings ("не перевірено") у Java?


Відповіді:


420

Іноді Java generics просто не дозволяє робити те, що ви хочете, і вам потрібно ефективно сказати компілятору, що те, що ви робите, дійсно буде законним під час виконання.

Зазвичай я відчуваю це біль, коли знущаюся із загального інтерфейсу, але є й інші приклади. Це, як правило , варто спробувати розробити спосіб уникнути попередження , а не пригнічуючи її ( Java Дженерики FAQ допомагає тут) , але іноді , навіть якщо це можливо, він згинається код з форми , так багато , що пригнічуючи попередження є акуратніше. Завжди додайте пояснювальний коментар у такому випадку!

В одній і тій самій FAQ про цю тему є кілька розділів на цю тему, починаючи з "Що таке" неперевірене "попередження? - це варто прочитати.


10
У деяких випадках можна уникнути цього, використовуючи YourClazz.class.cast (). Працює для контейнерів з одним загальним елементом, але не для колекцій.
akarnokd

Або бажано використовувати загальні підказки (YourClazz<?>)- Java ніколи не попереджає про такі ролі, оскільки вони безпечні. Однак це не завжди працює (детальну інформацію див. У поширених запитаннях про загальну інформацію).
Конрад Боровський

48

Це примітка для придушення компіляції попереджень про неперевірені загальні операції (не винятки), такі як касти. Це по суті означає, що програміст не бажав отримувати повідомлення про них, про які він уже знає, коли збирає певний біт коду.

Більше про цю конкретну примітку ви можете прочитати тут:

Придушити попередження

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

Анотації

Як вони сказали,

"Попередження" неперевірене "може виникнути при взаємодії зі застарілим кодом, написаним до появи генерики (обговорюється на уроці під назвою" Генерики ")."


19

Це також може означати, що поточна системна версія Java типу недостатньо хороша для вашого випадку. Щоб виправити це, було кілька пропозицій / хаків JSR : Введіть жетони, Super Type Tokken, Class.cast ().

Якщо ви справді потребуєте цього придушення, максимально звужте його (наприклад, не кладіть його на сам клас чи на довгий метод). Приклад:

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

   Collections.reverse(list);
   return list;
}

10

SuppressWarning анотації використовуються для придушення попереджень компілятора для анотованого елемента. Зокрема, uncheckedкатегорія дозволяє придушити попередження компілятора, згенеровані в результаті неперевірених типів.


Ваше посилання SupressWarning мертве; ось альтернатива: docs.oracle.com/javase/specs/jls/se6/html/…
James Daily

8

Просто: Це попередження, яким компілятор вказує, що він не може забезпечити безпеку типу.

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

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

Якби я не помацав тут @SuppressWarnings ("невірно"), у мене виникнуть проблеми з рядком, де я хочу повернути свій ResultList.

У ярлику означає безпеку типу: Програма вважається безпечною для типів, якщо вона компілюється без помилок і попереджень і не викликає будь-яких несподіваних ClassCastException s під час виконання.

Я будую на основі http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html


2
Це хороший приклад для ситуації, коли нам потрібно використовувати SuppressWarnings.
Джиммі

8

У 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;
}

Цей склад є безпечним, оскільки значення, збережене в порожній необов’язковій частині, неможливо отримати, тому не існує ризику несподіваних винятків з класів.


5

Ви можете придушити попередження компілятора і сказати загальним відомостям, що написаний вами код є законним згідно з ним.

Приклад:

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

5

Один фокус - створити інтерфейс, який розширює загальний базовий інтерфейс ...

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;

4

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

Компілятор попереджає програміста про це, але якщо програміст вже знає, вони можуть вимкнути ці жахливі попередження за допомогою SuppressWarnings.


1
JDK5 новий? Він закінчив більшу частину терміну служби "Кінець терміну служби".
Том Хотін - тайклін

Я знаю, що JDK 5 досить застарілий, я мав на увазі те, що він новий у тому сенсі, що він ввів нові можливості на Java, раніше не пропонувались у JDK 4. Також зауважте, що є ті, хто ще чекає JDK 7, перш ніж залишити JDK 5 позаду щоб прийняти JDK 6, я не можу пояснити, чому!
BakerTheHacker

2

Попередження, яким компілятор вказує, що він не може забезпечити безпеку типу. Термін "неперевірене" попередження вводить в оману. Це не означає, що попередження не перевірено жодним чином. Термін "неперевірений" позначає той факт, що компілятор і система виконання не мають достатньої інформації про тип для виконання всіх перевірок типів, які були б необхідні для забезпечення безпеки типу. У цьому сенсі певні операції "неперевірені".

Найпоширенішим джерелом "неперевірених" попереджень є використання сировинних типів. "неперевірені" попередження видаються, коли доступ до об'єкта здійснюється через змінну типу "необроблений", оскільки тип "необроблений" не забезпечує достатню інформацію про тип для виконання всіх необхідних перевірок типу.

Приклад (неперевіреного попередження у поєднанні із вихідними типами):

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");  
                      ^

Коли використовується метод додавання, компілятор не знає, чи безпечно додати об'єкт String до колекції. Якщо TreeSet - це колекція, що містить 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;

Лит, цільовий тип якого є (параметризований тип бетону чи обмеженого шару) або параметр типу, не є безпечним, якщо в процесі виконання є перевірка динамічного типу. Під час виконання доступно лише стирання типу, а не точний статичний тип, який видно у вихідному коді. В результаті частина виконуваної ролі виконується на основі стирання типу, а не на точному статичному типі.

У прикладі, передача Wrapper перевірятиме, чи об'єкт, повернутий з super.clone, є Wrapper, а не це обгортка з певним типом членів. Аналогічно, заклики до параметру типу T передаються для типу Object під час виконання та, ймовірно, повністю оптимізовані. Через стирання типу система виконання не може виконувати більш корисні перевірки типу під час виконання.

Певним чином, вихідний код вводить в оману, оскільки він говорить про те, що виконується передача відповідному цільовому типу, а насправді динамічна частина трансляції лише перевіряє стирання типу цільового типу. Попередження "неперевірене" видається, щоб привернути увагу програміста до цієї невідповідності між статичним та динамічним аспектом амплуа.

Будь ласка, зверніть увагу: Що таке "неперевірене" попередження?


2

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

@SuppressWarnings доручає компілятору ігнорувати або придушувати вказане попередження компілятора в примітці з примітками та всі програмні елементи всередині цього елемента. Наприклад, якщо клас позначається для придушення певного попередження, то попередження, створене в методі всередині цього класу, також буде відокремлено.

Можливо, ви бачили @SuppressWarnings ("невірно") і @SuppressWarnings ("серійний"), два найпопулярніші приклади анотації @SuppressWarnings. Former використовується для придушення попередження, що генерується через неперевірену трансляцію, тоді як пізніше попередження використовується для нагадування про додавання SerialVersionUID у клас Serializable.

Детальніше: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-uncont-raw-serial.html#ixzz5rqQaOLUa

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.