@SuppressWarnings в java (list of warnings) список предупреждений
1) Praemonitus praemunitus (предупреждён, значит, вооружён)
Практически все компиляторы в процессе компилирования исходного программного кода выполняют статический анализ этого кода, что позволяет идентифицировать и предупреждать о наличии некоторых общих ошибок программирования. Положительный эффект заключается в том, что каждое имеющееся предупреждение - потенциальная проблема, и чем раньше эта проблема выявляется (в данном случае - уже на этапе компиляции), тем дешевле её решение. В целом, многие опытные разработчики придерживаются мнения, что конечный код не должен вызывать предупреждений компилятора. Более того, в некоторых компаниях идут дальше и настраивают политики систем контроля версий таким образом, чтобы коммиты не вызывали подобных предупреждений.
Однако жизнь такова, что иногда исключения из строгих правил всё-таки возникают. И оказывается, что в каком-то конкретном случае выдаваемое компилятором предупреждение легально, и что было бы здорово указать компилятору проигнорировать конкретное предупреждение. Как вообще можно управлять политикой предупреждений в java?
2) Опция компилятора -Xlint
Пусть у нас есть следующий метод, в котором имеется потенциальная проблема: использование коллекции без generics.
Казалось бы, всё хорошо. Однако с помощью -Xlint:name мы можем управлять целыми типами предупреждений, и не можем выделить отдельные классы, методы, переменные и пр. И тут на помощь приходит аннотация @SupressWarnings.
3) Аннотация @SupressWarnings
Интерфейс: public interface SuppressWarnings
Реализует: интерфейс Annotation
Появился: jdk 1.5
JavaDocs: http://docs.oracle.com/javase/7/docs/api/java/lang/SuppressWarnings.html (eng), http://doc.java.sun.com/DocWeb/api/java.lang.SuppressWarnings (ru)
Параметры: String[] value - множество предупреждений в аннотированном элементе, о которых компилятор умалчивает.
Допускаются дублирующиеся имена. Второе и все последующие упоминания одного и того же имени игнорируются. Наличие неизвестных компилятору имён не является ошибкой: компиляторы должны игнорировать любые имена предупреждений, которые они не могут распознать. Однако, допускается генерация предупреждения, если аннотация содержит неизвестное имя предупреждения. Производители компиляторов должны документировать имена предупреждений, которые они поддерживают с данным типом аннотации. Поощряется сотрудничество для поддержания одинаковых имён среди разнообразных компиляторов.
Примеры: @SuppressWarnings("unchecked"), @SuppressWarnings(value="unchecked"), @SuppressWarnings({"unused", "deprecation"})
Теория.
Аннотация @SupressWarnings указывает на то, что именованное предупреждение (warning) компилятора должно быть подавлено в аннотируемом элементе (и во всех содержащихся в нём программных элементах). Множество подавленных предупреждений в данном элементе - это супермножество подавленных предупреждений во всех вложенных элементах. К примеру, если вы аннотируете класс для подавления одного предупреждения и аннотируете метод для подавления другого, то в методе будут подавляться оба предупреждения. Аннотацию всегда следует использовать как можно ближе к той части кода, для которой она необходима - это более эффективно. Так, если требуется подавить предупреждение в специфичном методе, нужно аннотировать скорее этот метод, чем весь класс, который его содержит.
Пример использованного ранее метода с добавленными аннотациями:
Eclipse platform help: Excluding warnings using @SuppressWarnings. С IntelliJ IDEA немного сложнее, найти подобный список не получилось; похоже, что в этой IDE он разбросан по мощному инструменту InspectionGadgets.
Давайте рассмотрим подробнее набор предупреждений, поддерживаемых Sun-овским компилятором. Итак, можно подавлять предупреждения, связанные с:
4) Итого
- предупреждения компилятора - хорошая возможность проверить свой код на наличие проблем определённых типов;
- на практике следует добиваться того, чтобы код компилировался без предупреждений;
- однако в некоторых случаях предупреждений не избежать;
- опция компилятора -Xlint позволяет включать/отключать выдачу предупреждений определённых типов;
- появившаяся в java 5 аннотация @SuppressWarning позволяет решать эту же задачу гораздо более гибко;
- нужно помнить, что как опции -Xlint, так и аннотация @SuppressWarning зависят от используемых компилятора и IDE.
1) Praemonitus praemunitus (предупреждён, значит, вооружён)
Практически все компиляторы в процессе компилирования исходного программного кода выполняют статический анализ этого кода, что позволяет идентифицировать и предупреждать о наличии некоторых общих ошибок программирования. Положительный эффект заключается в том, что каждое имеющееся предупреждение - потенциальная проблема, и чем раньше эта проблема выявляется (в данном случае - уже на этапе компиляции), тем дешевле её решение. В целом, многие опытные разработчики придерживаются мнения, что конечный код не должен вызывать предупреждений компилятора. Более того, в некоторых компаниях идут дальше и настраивают политики систем контроля версий таким образом, чтобы коммиты не вызывали подобных предупреждений.
Однако жизнь такова, что иногда исключения из строгих правил всё-таки возникают. И оказывается, что в каком-то конкретном случае выдаваемое компилятором предупреждение легально, и что было бы здорово указать компилятору проигнорировать конкретное предупреждение. Как вообще можно управлять политикой предупреждений в java?
2) Опция компилятора -Xlint
Пусть у нас есть следующий метод, в котором имеется потенциальная проблема: использование коллекции без generics.
package by.father.examples.warnings;Итак, пытаемся компилировать:
import java.util.ArrayList;
import java.util.List;
public class MethodWithUncheckedOperation {
public void someUnusedMethodWithUncheckedOperation () {
List list = new ArrayList();
list.add("element");
list.get(0).toString();
}
}
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>java -versionКомпиляция прошла без предупреждений, однако нам сделали замечание. Смотрим, что нам предложит компилятор в списке опций:
java version "1.6.0_33"
Java(TM) SE Runtime Environment (build 1.6.0_33-b03)
Java HotSpot(TM) Client VM (build 20.8-b03, mixed mode, sharing)
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>javac MethodWithUncheckedOperation.java
Note: MethodWithUncheckedOperation.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>javac -XВыясняется, что опция -Xlint позволяет включить все рекомендуемые предупреждения, а -Xlint:name - только необходимые (при этом приводится список поддерживаемых компиляторов предупреждений). Попробуем:
-Xlint Enable recommended warnings
-Xlint:{all,cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides,-cast,-deprecation,-divzero,-empty,-unchecked,-fallth
rough,-path,-serial,-finally,-overrides,none}Enable or disable specific warnings
...
These options are non-standard and subject to change without notice.
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>javac -Xlint:all MethodWithUncheckedOperation.javaТаким образом,
MethodWithUncheckedOperation.java:13: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List
list.add("element");
^
1 warning
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>javac -Xlint:unchecked MethodWithUncheckedOperation.java
MethodWithUncheckedOperation.java:13: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List
list.add("element");
^
1 warning
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>javac -Xlint:none MethodWithUncheckedOperation.java
Note: MethodWithUncheckedOperation.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
- по умолчанию компилятор не выдаёт предупреждения (равноценно применению -Xlint:none или стандартной -nowarn);
- применение опции -Xlint:name позволяет нам сказать компилятору, нужно ли формировать предупреждения, и какие именно;
- список доступных параметров -Xlint является "компиляторо-зависимым"; примеры списков предупреждений, доступных для подавления в компиляторах IBM 1.6.0 JDK for Linux x86_64 и Sun 1.6.0_u14 for Linux x86_64, можно посмотреть тут: Eclipse SuppressWarnings Annotation. В целом, они ничем не отличаются от только что представленного варианта. А вот вывод для компилятора Sun 1.5.0:
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>"C:\Java\jdk1.5.0_12\bin\java.exe" -version
java version "1.5.0_12"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04)
Java HotSpot(TM) Client VM (build 1.5.0_12-b04, mixed mode)
E:\warni\dev\examples\src\main\java\by\father\examples\warnings>"C:\Java\jdk1.5.0_12\bin\javac.exe" -X
-Xlint Enable recommended warnings
-Xlint:{all,deprecation,unchecked,fallthrough,path,serial,finally,-deprecation,-unchecked,-fallthrough,-path,-serial,-finally}Enable or disable specific warnings
- следует помнить, что опции с ключом -X объявлены как нестандартные со всеми вытекающими последствиями.
Казалось бы, всё хорошо. Однако с помощью -Xlint:name мы можем управлять целыми типами предупреждений, и не можем выделить отдельные классы, методы, переменные и пр. И тут на помощь приходит аннотация @SupressWarnings.
3) Аннотация @SupressWarnings
Интерфейс: public interface SuppressWarnings
Реализует: интерфейс Annotation
Появился: jdk 1.5
JavaDocs: http://docs.oracle.com/javase/7/docs/api/java/lang/SuppressWarnings.html (eng), http://doc.java.sun.com/DocWeb/api/java.lang.SuppressWarnings (ru)
Параметры: String[] value - множество предупреждений в аннотированном элементе, о которых компилятор умалчивает.
Допускаются дублирующиеся имена. Второе и все последующие упоминания одного и того же имени игнорируются. Наличие неизвестных компилятору имён не является ошибкой: компиляторы должны игнорировать любые имена предупреждений, которые они не могут распознать. Однако, допускается генерация предупреждения, если аннотация содержит неизвестное имя предупреждения. Производители компиляторов должны документировать имена предупреждений, которые они поддерживают с данным типом аннотации. Поощряется сотрудничество для поддержания одинаковых имён среди разнообразных компиляторов.
Примеры: @SuppressWarnings("unchecked"), @SuppressWarnings(value="unchecked"), @SuppressWarnings({"unused", "deprecation"})
Теория.
Аннотация @SupressWarnings указывает на то, что именованное предупреждение (warning) компилятора должно быть подавлено в аннотируемом элементе (и во всех содержащихся в нём программных элементах). Множество подавленных предупреждений в данном элементе - это супермножество подавленных предупреждений во всех вложенных элементах. К примеру, если вы аннотируете класс для подавления одного предупреждения и аннотируете метод для подавления другого, то в методе будут подавляться оба предупреждения. Аннотацию всегда следует использовать как можно ближе к той части кода, для которой она необходима - это более эффективно. Так, если требуется подавить предупреждение в специфичном методе, нужно аннотировать скорее этот метод, чем весь класс, который его содержит.
Пример использованного ранее метода с добавленными аннотациями:
@SuppressWarnings({"unchecked", "unused"})Таким образом, с помощью аннотации мы можем помечать отдельные классы, методы и переменные, что даёт нам высокую гибкость настройки. Более того, различные IDE расширяют список поддерживаемых предупреждений (соответственно, мы получаем compiler-specific + IDE-specific списки). Например, список параметров для Eclipse можно посмотреть здесь
public void someUnusedMethodWithUncheckedOperation () {
List list = new ArrayList();
list.add("element");
list.get(0).toString();
}
Eclipse platform help: Excluding warnings using @SuppressWarnings. С IntelliJ IDEA немного сложнее, найти подобный список не получилось; похоже, что в этой IDE он разбросан по мощному инструменту InspectionGadgets.
Давайте рассмотрим подробнее набор предупреждений, поддерживаемых Sun-овским компилятором. Итак, можно подавлять предупреждения, связанные с:
- all - любые;
- cast - приведением типов;
- deprecation (dep-ann) - использованием устаревшего кода;
- divzero - делением на нуль;
- empty - ? (не совсем понятно, информации не нашёл, возможно, связано с наличием пустых блоков?);
- unchecked - непроверенными операциями;
- fallthrough - некорректным использованием оператора switch (например, когда хотя бы в одном из case'ов пропущен завершающий break);
- path - обсутствием заданных директорий (входящих в classpath, sourcepath и т.д.);
- serial - пропуском поля serialVersionUID для сериализуемого класса;
- finally - наличием некорректных блоков finally;
- overrides - некорректным переопределением (например, переопределён equals(), но не hashCode()).
4) Итого
- предупреждения компилятора - хорошая возможность проверить свой код на наличие проблем определённых типов;
- на практике следует добиваться того, чтобы код компилировался без предупреждений;
- однако в некоторых случаях предупреждений не избежать;
- опция компилятора -Xlint позволяет включать/отключать выдачу предупреждений определённых типов;
- появившаяся в java 5 аннотация @SuppressWarning позволяет решать эту же задачу гораздо более гибко;
- нужно помнить, что как опции -Xlint, так и аннотация @SuppressWarning зависят от используемых компилятора и IDE.
+1
ОтветитьУдалитьСтатья помогла реально. Спасибо
Реалменте помогла!
ОтветитьУдалитьХорошая статья
ОтветитьУдалить