Иногда, просматривая код, я вижу, что многие методы определяют аннотацию:
@SuppressWarnings("unchecked")
Что это значит?
Иногда, просматривая код, я вижу, что многие методы определяют аннотацию:
@SuppressWarnings("unchecked")
Что это значит?
Иногда Java-дженерики просто не позволяют делать то, что вы хотите, и вам нужно эффективно сообщать компилятору, что то, что вы делаете, действительно будет законным во время выполнения.
Обычно я нахожу это болью, когда я издеваюсь за общим интерфейсом, но есть и другие примеры. Обычно стоит попытаться выработать способ избежать предупреждения, а не подавлять его (здесь помогает "Что такое" непроверенное "предупреждение?" - это стоит того читать.
Это аннотация для подавления компиляции предупреждений о непроверенных общих операциях (а не исключениях), таких как отбрасывания. По сути, это означает, что программист не хотел получать уведомления об этом, о котором он уже знает при компиляции определенного бита кода.
Подробнее об этом конкретном примечании вы можете прочитать здесь:
Кроме того, Oracle предоставляет некоторую учебную документацию об использовании аннотаций здесь:
Как они выразились,
"Предупреждение" непроверенное "может возникать при взаимодействии с устаревшим кодом, написанным до появления дженериков (обсуждается в уроке под названием Generics).
Это также может означать, что текущая версия системы типа Java недостаточно хороша для вашего случая. Было несколько предложений JSR/взломало, чтобы исправить это: Введите токены, Super Type Токены, Class.cast().
Если вам действительно нужно это подавление, сушите его как можно больше (например, не кладите его на сам класс или на длинный метод). Пример:
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.
В средствах безопасности типа быстрого доступа: программа считается безопасной для типов, если она компилируется без ошибок и предупреждений и не вызывает непредвиденных исключений 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>> {}
Затем вы можете проверить его с помощью экземпляра перед трансляцией...
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;
Насколько я знаю, на данный момент это связано с подавлением предупреждений о дженериках; generics - это новая конструкция программирования, не поддерживаемая в версиях 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 в коллекцию. Если 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, оболочкой, а не оболочкой с определенным типом членов. Аналогично, приведение к параметру типа T приведено к типу Object во время выполнения и, вероятно, полностью оптимизировано. Из-за стирания типа система времени выполнения не может выполнять более полезные проверки типов во время выполнения.
В некотором смысле, исходный код вводит в заблуждение, потому что он предполагает, что приведение к соответствующему целевому типу выполняется, в то время как на самом деле динамическая часть приведения проверяет только стирание типа целевого типа. Предупреждение "unchecked" выдается, чтобы привлечь внимание программиста к этому несоответствию между статическим и динамическим аспектом приведения.
Пожалуйста, обратитесь: Что такое "непроверенное" предупреждение?
Аннотация @SuppressWarnings является одной из трех встроенных аннотаций, доступных в JDK и добавленных вместе с @Override и @Deprecated в Java 1.5.
@SuppressWarnings указывает компилятору игнорировать или подавлять указанное предупреждение компилятора в аннотированном элементе и все элементы программы внутри этого элемента. Например, если класс аннотирован для подавления определенного предупреждения, то предупреждение, созданное в методе внутри этого класса, также будет разделено.
Возможно, вы видели @SuppressWarnings ("непроверенный") и @SuppressWarnings ("серийный"), два самых популярных примера аннотации @SuppressWarnings. Прежний используется для подавления предупреждения, генерируемого из-за непроверенного приведения, в то время как последующее предупреждение используется для напоминания о добавлении SerialVersionUID в класс Serializable.