17

У нас есть проект Java. Мы включаем -Xlint (включить предупреждения) и -Werror (обратите внимание на предупреждение как ошибка) для javac, чтобы убедиться, что наш код не содержит предупреждений. Недавно мы решили отказаться от класса. В некоторых случаях проблема заключается в том, что @SuppressWarnings("deprecation") не будет подавлять предупреждение об отказе, что приведет к сбою сборки. Ниже приведен список вариантов использования, на которые я столкнулся:Как избежать предупреждений об устаревании, когда @SuppressWarnings ("deprecation") не работает?

  1. Импортирован из других классов, не относящихся к классу.
  2. Импортировано из других категоризированных классов.
  3. Родительский класс.
  4. Тип параметра. Например

    @SuppressWarnings("deprecation") 
    public class Foo extends Bar<DeprecatedClass> 
    { ... } 
    

    Тем не менее, эта не имеет никакого предупреждения, даже не подавляет:

    @Deprecated 
    public class DeprecatedClass extends Bar<DeprecatedClass> 
    { ... } 
    

AFAIK, нет синтаксиса для аннотирования импорта, так что для случая 1 и 2 наше решением является либо импортировать *, либо не импортировать. В случае 3 и 4, как Java 6, так и 7 не подавляют предупреждение. Java 8 будет корректно подавлять его (возможно, ошибка исправлена). Пока нет решения для этого.

К сожалению, на данный момент мы должны поддерживать Java 6, 7 и 8. Есть ли способ справиться с этой проблемой? Это дорожный блок для нашей эволюции Java API.

ADDENDUM

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

  • Мы принизить класс Foo и Bar, где Foo проходит Bar. Это вопрос 2 и 3 в моем вопросе.
  • Мы отказываем классу Foo и Bar, где Foo распространяется Collection<Bar>. В этом случае 2 и 4.
  • Мы должны оставить все тестовые коды для класса Foo и Bar. Код теста импортирует эти классы. В этом случае 1.

Зачем хранить тест? Не забывайте, что если обнаружена серьезная ошибка (например, утечка памяти, проблема безопасности), и клиенты не могут легко перейти на новую версию, нам все равно нужно предоставить исправление ошибок для старого API. И все изменения должны быть проверены.

Я считаю, что наша ситуация должна быть довольно распространена в разработке программного обеспечения и разработке API. Удивительно, что для такого исправления Java потребовалось много времени (до Java 8).

+2

Есть, вероятно, не так много вариантов. Вы можете изменить процесс сборки, чтобы не выполнять «-Werror», если не задано значение target = 8, или исключить предупреждения об устаревании, так как это кажется сломанным в 6 и 7. Или вы не выполняете стандартную устаревание (например, неудачная альтернатива): Skip устаревание и сразу удалить плохой класс, «обесценить» его, разместив примечание на веб-сайте/javadoc, или в случае, если это работает, также обесценивает каждый класс, который использует его как параметр типа, даже если он останется в том случае, если устаревший класс будет исчезают. Также http://stackoverflow.com/a/20909204/995891 относительно 1) & 2) – zapl

+0

Я думаю, что не осудить случай 3 и поставить '@ устаревший' в Джавадоке может быть последним, если не существует лучшего подхода. –

+0

Поскольку вы ссылаетесь на него как на тип, а не на класс, можете ли вы расширять его с помощью универсального типа и затем переводить на 'DeprecatedClass' позже, с предупреждением о подавлении? – CharlieS

ответ

7

Прошу прощения, что у меня нет решения проблемы, с которой вы столкнулись, хотя, как вы заметили, был некоторый прогресс. Мы пытались избавиться от всех предупреждений компиляции Java в самом JDK, и это был долгий, сложный процесс. Во время разработки JDK 8 в 2011 году я помог kick off the warnings cleanup effort, а позже co-presented a JavaOne talk (slides and audio) по этому вопросу.

Совсем недавно мой коллега Джо Дарси продолжил работу по очистке предупреждений и проработал различные категории предупреждений и имеет finally reached deprecation warnings. Как вы отметили, были некоторые ошибки в обработке компилятором подавления предупреждений об устаревании, таких как JDK-6480588, который был исправлен в JDK 8. К сожалению, в JDK 8 все еще невозможно подавить предупреждения об импорте устаревших предметов. Эта ошибка, JDK-8032211, была исправлена ​​совсем недавно в нашей линии разработки JDK 9. Фактически, мы все еще настраиваем обработку аннотации @Deprecated. Например, ошибка JDK-6481080 поясняет, что попытка использования @Deprecated в файле package-info.java фактически не обесценивает пакет; эта ошибка была исправлена ​​только на прошлой неделе. И есть more work to be done, но на данный момент это несколько умозрительно.

JDK сталкивается с аналогичными проблемами с вашими, поскольку мы должны поддерживать устаревшие API-интерфейсы для клиентов, которые все еще используют их. Но поскольку мы используем и внедряем такие API внутри, у нас есть много предупреждений об устаревании для подавления. На момент написания этой статьи, в нашей линии разработки JDK 9, нам еще не удалось скомпилировать систему без предупреждений об устаревании. В результате, javac варианты линт предупреждений еще:

-Xlint:all,-deprecation 

Вы, вероятно, придется отключить предупреждения устаревания в вашей компиляции, а, особенно, если вы все еще опираясь на JDK 6. Я не вижу путь вокруг него в этот момент.

одно замечание на одном из случаев устаревания:

@Deprecated 
public class DeprecatedClass extends Bar<DeprecatedClass> { ... } 

Это не выдает предупреждение устаревания, и не должно.В поле Java Language Specification, section 9.6.4.6 указано, что предупреждения об устаревании не выдаются, если использование устаревшего объекта находится внутри объекта, который сам устарел.

+0

Спасибо за разъяснение и обмен разработкой JDK. –

+0

Это последнее примечание интересно, потому что я клянусь, что мне пришлось добавить @SuppressWarnings («устаревший») на методы, которые уже были @Deprecated до ... – Trejkaz

+0

@Trejkaz Пожалуйста, отправьте пример, если найдете его. –

-3

Обычно, когда вы осуждаете класс, вы не хотите, чтобы кто-либо использовал его в более поздних версиях. Кроме того, ваша кодовая база также должна прекратить использование устаревшего класса. Это выглядит странно, когда вы говорите, что все не используют класс MySuperDeprecatedUtil, но продолжают использовать его в своей кодовой базе.

Если вам нужно использовать свой класс MySuperDeprecatedUtil в каком-то другом классе - вы должны пометить класс, в котором вы его используете, как @Deprecated - каждый класс, который использовал устаревший код, должен быть либо устаревшим, либо выдавать предупреждения компиляции, либо должен быть удален , или следует прекратить использование устаревшего кода.

Если вы не можете прекратить использовать свой класс - может быть, еще слишком рано его осуждать?

В моей практике, когда я хочу отказаться от какого-либо класса, я создаю класс замены, например. MySuperFreshUtil. Переключайте все классы с помощью MySuperDeprecatedUtil на MySuperFresh, используя, где это возможно, интерфейсы (если это невозможно), используйте FQCN и метод меток как устаревший). Отметьте MySuperDeprecatedUtil как @Deprecated и добавьте комментарий, какой класс и как следует использовать вместо этого. Затем я фиксирую эти изменения в одном списке изменений.

+1

Предположим, что у вас есть 10 реализаций абстракции формата файла, для обратной совместимости. Люди должны использовать только последний формат, поэтому вы не соглашаетесь с другим 9. Фабрика, которая создает правильный объект для данного файла, по-прежнему должна создавать экземпляры другого 9. Вы не можете просто удалить этот метод, потому что он сломается назад совместимость. Вы также не можете отказаться от заводского метода, потому что он все еще используется при чтении файлов. Таким образом, по этой логике единственным решением является удаление 9 старых реализаций, поэтому они больше не устарели. Я не уверен, что хочу. – Trejkaz

1

Рассмотрите возможность использования -Xmaxwarns, вы можете контролировать, сколько предупреждений перед остановкой.

Или попробуйте собрать количество предупреждений и не выполнить процесс интеграции, а не компилировать.

Например: https://issues.apache.org/jira/browse/HADOOP-11252. Каждый код, переданный в проект hadoop, должен передать автоматическое CI, и он дает -1 для увеличения количества предупреждений.

Смежные вопросы