当前位置:  开发笔记 > 编程语言 > 正文

JetBrains的@Contract注释

如何解决《JetBrains的@Contract注释》经验,为你挑选了3个好方法。

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



1> dcsohl..:

首先,我应该说这个注释仅供IDEA用于检查可能的错误.Java编译器几乎完全忽略它(它将在编译的工件中但不起作用).话说回来...

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

可能的输入是_(任意值), ,null(!null非空),false并且true,和可能的输出添加fail到该列表中.

因此,例如,null -> false意味着,如果提供null输入,false则结果是布尔值.null -> false; !null -> true对此进行扩展以表示null始终返回false并且非null值将始终返回true,等等.最后,null -> fail表示如果将空值传递给该方法将抛出异常.

对于多参数示例,null, !null -> fail意味着在双参数方法中,如果第一个参数为null而第二个参数不为null,则会抛出异常,保证.

如果方法不更改对象的状态,但只返回新值,则应设置pure为true.



2> Makoto..:

在官方文件规定了正式的语法的注释所有支持和认可的价值观.

通俗地说:

合同可以包含1个或多个与之相关的条款

一个条款总是如此 [args] -> [effect]

Args是1个或更多约束,定义为 any | null | !null | false | true

效果只是一个约束或 fail

让我们来看一个简单的例子 - 我最喜欢的一个例子是,"无论你传递给这个方法,它都会抛出异常."

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

在这里,我们使用_或"任何"表示无论我们传递给这个方法的是什么,我们都会抛出异常.

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

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

IntelliJ提出了一些警告.

在此输入图像描述

当我们处于void方法时,我们说我们正在返回一个布尔值(显然)很不高兴...

在此输入图像描述


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

您希望保证您返回true或false

您希望保证在给定约束的情况下返回非null值

您希望明确表示您可以在给定约束的情况下返回空值

您希望明确表示您将在给定约束的情况下抛出异常

这并不是说@Contract完美; 离得很远.它不能在某些情况下进行非常深入的分析,但在代码库中使用它可以让您的工具免费进行这种分析.



3> EntangledLoo..:

org.jetbrains.annotations.Contract注释如何工作?

虽然以前的答案是提供信息的,但我不认为他们在你的问题中解决了"工作"这个词.也就是说,他们没有解释IntelliJ在幕后做什么来实现他们的注释,这样你就可以从头开始轻松地构建自己的注释.

如果您浏览下面的源代码,您可能会认为它看起来有点过于复杂(或者至少是冗长的)@NotNull.我同意你的观点,这也是我一般避免使用@Contract不像"简单而简单"(如@NotNull)的条款,而是直接使用JavaDoc我的先决条件的一个原因.

一般不鼓励使用复杂的合同注释 -尽管我可能会因为跳过这条时髦的新火车而感到厌恶 - 这里有一些原因:

注释可以是复杂的 - 例如在他们自己的定义中具有多个嵌套注释和/或具有图灵完整性外观的"语法" .通过掩盖隐藏/抽象层背后的错误的真正罪魁祸首并且未能生成最初预期的警告,这可能导致编译时的错误信任感.

与我之前的观点相似但不同的是,注释通常会在一些关键字中隐藏开发人员的大量逻辑,从而产生难以理解的人类代码和/或难以调试的异常行为.

应用程序配置通常被视为伪装成注释.看看Spring框架.

定义合同的语法是相当大的(恕我直言)非常丑陋和Makefile-ish.例如,看一下JetBrains注释定义和分散在其repo中的支持文件.注意众多的XML文件和大量的自我引用?我写作和支持并不是很有趣,特别是考虑到Android和更大的Java社区之间来回的注释不断演变的本质.

需要考虑的一些问题:

当注释的源代码接近它注释的源代码的复杂性时,它是否走得太远?

下面的代码段是否真的比在运行时检查null并使用stacktraces记录异常要好得多?包含类似的内容会强制您的用户阅读,理解并可能修复另一组定义注释的依赖项.

借用另一篇关于契约语义的冗长帖子,我认为只会进一步说明我的观点:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;

/**
 * This annotation can be applied to a package, class or method to indicate that the class fields,
 * method return types and parameters in that element are not null by default unless there is: 
    *
  • An explicit nullness annotation
  • The method overrides a method in a superclass (in which * case the annotation of the corresponding parameter in the superclass applies)
  • there is a * default parameter annotation applied to a more tightly nested element.
*

* @see /sf/ask/17360801/ */ @Documented @Nonnull @TypeQualifierDefault( { ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface NotNullByDefault { }

什么时候和什么合同你应该使用?

我建议坚持从他们的名字中明确表达其意图的那种,并避免那些具有他们自己的语义和语言定义的人.

使用的示例 - 尽管使用前一个段 - 是@NotNull,但仅限于所有对象参数必须为null时.

要避免的排序的一个例子是 Android和IntelliJ @Contract(...).虽然我确实喜欢他们的IDE,但他们注释的细节非常复杂,最终变成了更多问题的根源和平台不兼容性让我追踪(不可否认的是,由于我几乎100%的时间在创作新合同时无知,但为什么这么难以正确?)

摘要/结论

注释是一个很好的想法,清楚地由程序员想要"编纂"他们的文档.我觉得他们最近走得太远了,把文档变成了带语义的代码,导致了一些严重的难题和尴尬的情况.更糟糕的是,它们有时会因为未能检测到自己实现中出现的问题而赋予编译时安全性的错误感.坚持非常简单,避免任何看起来像非Java语言的东西(这是你打算首先写的).

进一步阅读

这个简短的列表是StackOverflow和Web上的大多数关键(w /乐观!)来源的混合,我觉得这些来源说明了我的一些观点.

没有特别的顺序:

Java注释是一个很大的错误

注释,注释,无处不在

反对注释的参数

注释是不是很糟糕?

注释梦魇

邪恶的注释

毕竟,我刚刚意识到我可能仍未能完全解决你原来的问题:)


虽然这是值得讨论的,但这篇文章_also_并未回答有关`@ Contract`如何运作的问题.事实上,与其他答案不同,它根本没有解决实际提出的问题.我建议把它变成博客文章或其他东西.
推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有