注解Contract的使用
在测试SpringBoot的 Assert
时候,我给 Assert.isTrue
的 expression
强制写了 false 这时候我的IDEA会给这个方法下面画一个虚线,鼠标放上去会有下面的提示
很好玩这个是怎么做到的呢,为什么会有这个提示呢。我就点进去看了一下发现了一个注解
@Contract("false, _ -> fail")
这是什么呢?不管三七二一先点进去看看这是个啥,看到了一句话
Specifies some aspects of the method behavior depending on the arguments. Can be used by tools for advanced data flow analysis. Note that this annotation just describes how the code works and doesn't add any functionality by means of code generation.
Inspired by org. jetbrains. annotations. Contract, this variant has been introduced in the org. springframework. lang package to avoid requiring an extra dependency, while still following the same semantics.
大概的功能就是为静态分析工具(主要是 IntelliJ IDEA)提供关于方法行为的元数据(metadata) 。它像一个“合同”或“契约”,精确地描述了一个方法的输入(参数)和输出(返回值)之间的关系。这个注解对程序的运行时没有任何影响,它不会被 Spring 容器解析,也不会改变代码的执行逻辑。它的唯一目的就是帮助 IDE 和其他静态分析工具更智能地理解你的代码,从而提供更精确的警告、错误提示和代码优化建议。而且这个功能是 Spring 从 jetbrains 借鉴的
查了一下代码发现不止 Assert
用了连 org.springframework.util.StringUtils
也在使用这个。挺有趣这样就可以通过 IDEA 直接提示我这个地方不能为空了,我也自己写一个试试
@Contract("null -> fail; _ -> !null")
private String getMsg(String s) {
if (s == null || s.isEmpty()) {
throw new IllegalArgumentException("参数不能为空");
}
return s;
}
@Test
public void assertIsEmptyTest() {
getMsg(null);
}
写了之后发现 IDEA 果然提示我了
@Contract
的语法非常简洁,格式是 "<参数约束> -> <返回约束>"
,多个规则用分号 ;
分隔。
常用约束符号:
null
: 表示一个null
值。!null
: 表示一个非null
值。true
/false
: 表示布尔值。_
(下划线): 表示任意值(不关心参数的具体值)。fail
: 表示方法会抛出异常,不会正常返回。new
: 表示方法每次都返回一个新的对象。this
: 表示方法返回当前的实例。param1
,param2
, ...: 表示方法返回其第一个、第二个参数。
一些例子(从注释中扣出来的):
@Contract("_, null -> null") - 如果方法的第二个参数为null,则该方法返回null。
@Contract("_, null -> null; *,!null ->!null") - 如果方法的第二个参数为null,则该方法返回null;否则返回非null值。*
@Contract("true -> fail") - 一个典型的 assertFalse 方法,如果传入true则抛出异常。*
@Contract("* -> this") - 该方法总是返回其限定符(例如StringBuilder.append(String))。
@Contract("null -> fail; _ -> param1") - 如果第一个参数为null,该方法抛出异常,否则返回第一个参数(例如Objects.requireNonNull)。
@Contract("!null, _ -> param1; null,!null -> param2; null, null -> fail") - 该方法返回第一个非null参数,如果两个参数都为null则抛出异常(例如Objects.requireNonNullElse)。