【发布时间】:2015-01-11 08:37:35
【问题描述】:
我们有一个 Java 项目。我们为javac 启用-Xlint(启用警告)和-Werror(将警告视为错误)标志,以确保我们的代码没有警告。最近我们决定弃用一个类。问题是在某些情况下@SuppressWarnings("deprecation") 根本不会抑制弃用警告,从而导致构建失败。以下是我遇到的用例列表:
- 在其他未弃用的类中导入。
- 在其他已弃用的类中导入。
- 父类。
-
类型参数。例如
@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 发展的障碍。
附录
很多人问为什么我们仍然在我们自己的代码库中使用已弃用的类。原因是该项目是一个库,支持许多不同的客户端。在引入新的替代 API 时,我们必须首先弃用旧 API,将其保留在我们的代码库中,等待所有客户端迁移然后将其删除。常见的用例有以下三种:
- 我们弃用了
Foo和Bar类,其中Foo扩展了Bar。这是我的问题中的情况 2 和 3。 - 我们弃用了
Foo和Bar类,其中Foo扩展了Collection<Bar>。这是案例 2 和 4。 - 我们必须保留类
Foo和Bar的所有测试代码。测试代码导入这些类。情况 1 是这样。
为什么要保留测试?不要忘记,如果发现了严重的错误(例如内存泄漏、安全问题),并且客户端无法轻松迁移到新版本,我们仍然需要对旧 API 进行错误修复。所有更改都必须经过测试。
我觉得我们的情况在软件库开发和 API 演进中应该相当普遍。令人惊讶的是,Java 花了这么长时间(直到 Java 8)来修复这个错误。
【问题讨论】:
-
可能没有太多选择。您可以将构建过程更改为不执行
-Werror除非目标 == 8,或者排除弃用警告,因为这似乎在 6 和 7 中被破坏。或者您不执行标准弃用(imo 是一个不好的选择):跳过弃用并立即删除坏类,通过在 web/javadoc 上添加注释来“弃用”它,或者在可行的情况下也弃用每个使用它作为类型参数的类,即使它会保留以防被弃用的类会消失.还有stackoverflow.com/a/20909204/995891关于1)和2) -
如果没有更好的方法,我认为不弃用案例 3 并将
@deprecated放入 Javadoc 可能是最后的手段。 -
由于您将其引用为类型而不是类,您可以使用泛型类型进行扩展,然后转换为
DeprecatedClass,并在转换周围加上警告抑制吗? -
这有什么帮助?我认为Java泛型主要提供编译时类型检查。用
Object之类的东西替换它会破坏最初的目的。 -
在你的导入中是 DeprecatedClass 吗?我发现如果你在类的顶部有抑制,从导入中删除不推荐使用的类,并在代码中使用不推荐使用的类的完整包名,它就可以工作。
标签: java compilation compiler-warnings deprecated suppress-warnings