当前位置: 首页 > 知识库问答 >
问题:

当@SuppressWarnings(“弃用”)不起作用时,如何避免弃用警告?

田马鲁
2023-03-14

我们有一个Java项目。我们为javac启用了Xlint(启用警告)和Werror(将警告视为错误)标志,以确保我们的代码没有警告。最近我们决定不推荐一个类。问题是在某些情况下,SuppressWarnings(“弃用”)根本不会抑制弃用警告,从而导致生成失败。下面是我遇到的用例列表:

>

  • 在其他未弃用的类中导入。
  • 在其他已弃用的类中导入。
  • 家长班。
  • 类型参数。例如

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

    但是,即使没有“抑制”,此选项也没有警告:

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

    好吧,没有用于注释导入的语法,所以对于案例1和2,我们的解决方案是要么导入*要么避免导入。对于案例3和4,Java 6和7都不会抑制警告。Java 8将正确地抑制它(可能修复了一个bug)。到目前为止,还没有解决方案

    不幸的是,我们现在必须支持Java6、7和8。有办法解决这个问题吗?这是我们JavaAPI演进的障碍。

    附录

    许多人问,为什么我们仍然在自己的代码库中使用不推荐的类。原因是该项目是一个库,支持许多不同的客户。在引入新的替换API时,我们必须首先弃用旧API,将其保留在代码库中,等待所有客户端迁移,然后将其删除。有三种常见用例:

    • 我们弃用类FooBar,其中Foo扩展了Bar。这是我的问题中的情况2和3。
    • 我们弃用类FooBar,其中Foo扩展了Collection

    为什么要保留测试?不要忘记,如果发现了严重的错误(例如内存泄漏、安全问题),并且客户端无法轻松迁移到新版本,我们仍然需要为旧API提供错误修复。所有的变化都必须经过测试。

    我觉得我们的情况在软件库开发和API演进中应该是相当普遍的。令人惊讶的是,Java花了这么长时间(直到Java8)来修复这个错误。


  • 共有3个答案

    岳劲
    2023-03-14

    通常,当您不推荐该类时,您不希望任何人在以后的版本中使用它。此外,您的代码库也应该停止使用不推荐的类。当你说每个人都不要使用MySuperDeprecatedUtil类,而是继续在你的代码库中使用它时,这看起来很奇怪。

    如果您需要在其他类中使用您的MySuperDeprecatedUtil类-您应该将使用它的类标记为@Deprecated-每个使用弃用代码的类都应该弃用,或者会产生编译警告,或者应该被删除,或者应该停止使用弃用代码。

    如果你不能停止使用你的类——也许现在弃用它还为时过早?

    在我的实践中,当我想弃用某些类时,我会创建替换类,例如MySuperFreshUtil。在可能的情况下,使用MySuperDeprecatedUtil将所有类切换到MySuperFresh util保留接口(如果不可能-使用FQCN并将方法标记为弃用)。将MySuperDeprecatedUtil标记为@Deprecated并添加注释应该使用哪个类和如何代替。然后我在单个变更列表中提交此更改。

    宋瀚海
    2023-03-14

    考虑使用-Xmaxwarns,您可以控制停止之前的警告数量。

    或者尝试收集警告的数量并失败集成过程,而不是编译。

    例如:https://issues.apache.org/jira/browse/HADOOP-11252.提交到hadoop项目的每一个代码都需要通过自动CI,如果警告数量增加,它会给出-1。

    长孙鸿
    2023-03-14

    很抱歉,我没有办法解决你面临的问题,尽管正如你所观察到的,已经取得了一些进展。我们一直在努力消除JDK本身中的所有Java编译警告,这是一个漫长而艰难的过程。在2011年JDK 8开发期间,我帮助启动了警告清理工作,后来我就这个主题联合发表了一篇JavaOne演讲(幻灯片和音频)。

    最近,我的同事乔·达西(JoeDarcy)继续进行警告清理工作,并处理了不同的警告类别,最后得出了弃用警告。正如您所注意到的,编译器在处理抑制弃用警告时存在一些错误,例如JDK-6480588,它在JDK 8中已修复。不幸的是,在JDK 8中仍然无法抑制对不推荐项目导入的警告。这个bug JDK-8032211最近在我们的JDK 9开发线中被修复了。事实上,我们仍在调整已弃用注释的处理。例如,错误JDK-6481080说明试图在包信息中使用已弃用的。java文件实际上并不反对该包;上周刚刚修复了此错误。还有更多的工作要做,但在这一点上有些推测。

    JDK面临着与您类似的问题,因为我们必须为仍在使用它们的客户端维护已弃用的API。但是由于我们在内部使用和实现此类API,我们有很多弃用警告要抑制。截至本文撰写时,在我们的JDK 9开发行中,我们仍然无法在没有弃用警告的情况下编译系统。因此,lint警告的javac选项仍然是:

    -Xlint:all,-deprecation
    

    您可能还必须在编译中禁用弃用警告,尤其是在您仍在JDK 6上构建的情况下。现在我看不出有什么办法。

    关于其中一个弃用案例的最后一点注意事项:

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

    这不会发出弃用警告,也不应该发出。Java语言规范第9.6.4.6节规定,如果已弃用实体的使用在本身已弃用的实体内,则不会发出弃用警告。

     类似资料:
    • 问题内容: DeprecationWarning:需要一个整数(got类型为float)。不建议使用隐式转换为整数,并且在将来的Python版本中可能会删除隐式转换。 DeprecationWarning:需要一个整数(got类型为float)。不建议使用隐式转换为整数,并且在将来的Python版本中可能会删除隐式转换。 问题答案: 警告与的坐标参数有关。浮点坐标将表示的原点位于窗口像素之间。那没

    • 问题内容: 我有一个React组件,我想在单击时切换一个CSS类。 所以我有这个: 这个问题是ESLint不断告诉我“ this.refs”已贬值。 我该怎么办?我如何解决它而不使用折旧的代码? 问题答案: 您要引用的Lint规则称为 no-string-refs, 并通过以下方式警告您: 之所以收到此警告,是因为已实现了不赞成使用的使用方式(通过使用字符串)。根据您的React版本,您可以执行以

    • 问题内容: 我刚刚更新到Django v1.8,并在更新项目之前测试了本地设置,并且发出了弃用警告,这是我从未见过的,对我也没有任何意义。我可能只是忽略了某些内容或误解了文档。 现在,这对我提出了3个问题。 根据文档,Options.app_label除非模型不在应用程序模块之外,否则不是必需的,在我看来,不是这样。其次,无论如何,此行为在1.7中已被弃用,那么为什么它甚至成为问题? 这些应用程序

    • 我看到了许多在API上使用弃用注释的示例,以便将它们标记为“需要尽快更换”。 然而,在几乎所有这些情况下,代码开发人员不仅继续使用弃用的API,而且还抑制了弃用警告。 API开发人员的最佳意图似乎最终会创建更多与已实现的业务逻辑无关的代码——如果API已弃用但不断使用并抑制相关警告,则看起来充其量是代码的退化,并且在最坏的情况下替换弃用的库时是潜在的应用程序断点IMHO。 这个问题有没有切实可行的

    • 我是一个使用express.js.创建Web应用程序的node.js开发人员,现在我的问题是: 每当我在我的计算机上创建一个应用程序,npm就会安装它的东西并运行它(使用node app.js和nodemon),我会在控制台中收到以下消息: 这个应用很好用。但当我克隆在其他计算机上创建的应用程序时,我没有收到该消息,所以我假设我的计算机中有过时的东西。 我去了消息中提到的站点并证实了我的猜测。这是

    • 问题内容: 我已更新到swift 5,并且我使用的依赖项之一不会在swift 5中编译。我已修复它,但现在我在整个文件中收到350多个弃用警告。它们都与此类似: 不推荐使用:改用 这是代码的伪装(基本上只是调用ac库的函数): 作为参考,在上面的crypto_generichash_keybytes()中仅返回size_t,其签名为。 我发现(如该答案所述)解决该问题的方法应该是调用kPtr.ba