JetBrains的@Contract注释

2022-08-31 15:36:58

注释如何工作?IntelliJ IDEA如何支持它?org.jetbrains.annotations.Contract


答案 1

首先,我应该说这个注释只是为了让IDEA用来检查可能的错误。Java编译器将几乎完全忽略它(它将在编译的工件中,但没有效果)。话虽如此...

注释的目标是描述方法将遵守的协定,这有助于 IDEA 捕获可能调用此方法的方法中的问题。有问题的契约是一组分号分隔的子句,每个子句都描述了保证发生的输入和输出。因果关系用 分隔,并描述当您向方法提供 X 时,Y 将始终产生的情况。输入被描述为逗号分隔的列表,描述了多个输入的情况。->

可能的输入为(任何值)、、(非空值)和 ,并且可能的输出将添加到此列表中。_null!nullfalsetruefail

例如,意味着,如果输入,则布尔值就是结果。 对此进行扩展,说将始终返回,非值将始终返回 true,依此类推。最后,意味着如果向方法传递 null 值,则该方法将引发异常。null -> falsenullfalsenull -> false; !null -> truenullfalsenullnull -> fail

对于多参数示例,意味着在双参数方法中,如果第一个参数为 null,而第二个参数不为 null,则将引发异常,这是有保证的。null, !null -> fail

如果该方法不更改对象的状态,而只是返回一个新值,则应设置为 true。pure


答案 2

官方文档指定了注释的所有受支持和已识别值的正式语法

通俗地说:

  • 一个合同可以有 1 个或多个与之关联的条款
  • 子句始终[args] -> [effect]
  • 参数是 1 个或多个约束,定义为any | null | !null | false | true
  • 效果只是一个约束或fail

让我们看一个简单的例子 - 我最喜欢的一个是,“无论你传递到这个方法中,它都会引发一个异常。

@Contract("_-> fail")
public void alwaysBreak(Object o) {
    throw new IllegalArgumentException();
}

在这里,我们使用 或“any”来指示无论我们传入此方法的内容如何,我们都将引发异常。_

如果我们撒谎并说这种方法将无条件返回怎么办?true

@Contract("_-> true")
public void alwaysBreak(Object o) {
    throw new IllegalArgumentException();
}

IntelliJ对此提出了一些警告。

enter image description here

同样(显然)令人沮丧的是,当我们处于无效方法中时,我们说我们正在返回布尔值......

enter image description here


您会发现自己想要使用的主要时间是:@Contract

  • 您希望保证您返回的是真是假
  • 您希望保证在给定约束的情况下返回非 null 值
  • 您希望明确说明在给定约束的情况下可以返回 null 值
  • 您希望明确说明在给定约束的情况下将引发异常

这并不是说这是完美的;远非如此。它不能在某些上下文中进行非常深入的分析,但是在你的代码库中有这个可以让你的工具免费进行这种分析。@Contract


推荐