org.jetbrains.annotations.Contract
アノテーションは動作しますか? IntelliJ IDEA=それをどのようにサポートしますか?
最初に、この注釈はIDEAがエラーの可能性をチェックするためにのみ使用されることを意味します。Javaコンパイラはそれをほぼ完全に無視します(コンパイルされたアーティファクトに含まれますが、効果はありません。
アノテーションの目的は、メソッドが従うcontractを記述することであり、これはIDEAこのメソッドを呼び出す可能性のあるメソッドの問題をキャッチするのに役立ちます。問題のコントラクトはセミコロンで区切られた句のセットで、それぞれが発生が保証される入力と出力を記述します。原因と結果は->
で区切られ、メソッドにXを提供する場合、Y will always result。入力はカンマ区切りリストとして記述され、複数の入力の場合を記述します。
可能な入力は_
(任意の値)、null
、!null
(非ヌル)、false
およびtrue
であり、可能な出力はこのリストにfail
を追加します。
したがって、たとえば、null -> false
は、null
入力が提供されると、false
ブール値が結果になることを意味します。 null -> false; !null -> true
は、これを拡張して、null
がalwaysfalse
を返し、null
以外の値がalways trueを返すなどと言います。最後に、null -> fail
null値を渡すと、メソッドは例外をスローします。
複数の引数の例の場合、null, !null -> fail
は、2つの引数のメソッドで、最初の引数がnullで2番目の引数がnullでない場合、例外がスローされ、保証されることを意味します。
メソッドがオブジェクトの状態を変更せず、新しい値を返すだけの場合は、pure
をtrueに設定する必要があります。
公式ドキュメント は、注釈に対してサポートおよび認識されているすべての値の 正式な文法 を指定します。
素人の言葉で:
[args] -> [effect]
any | null | !null | false | true
として定義されますfail
のみです簡単な例を見てみましょう-私のお気に入りの1つは、「このメソッドに渡すものは何でも、例外をスローします」です。
@Contract("_-> fail")
public void alwaysBreak(Object o) {
throw new IllegalArgumentException();
}
ここでは、_
、または「any」を使用して、このメソッドに何を渡すかに関係なく、例外をスローすることを示しています。
このメソッドが無条件にtrue
を返すと嘘をついて言ったらどうでしょうか?
@Contract("_-> true")
public void alwaysBreak(Object o) {
throw new IllegalArgumentException();
}
IntelliJはそれについていくつかの警告を出します。
voidメソッドにいるときにブール値を返すと言ったのも(明らかに)動揺しています...
@Contract
を使用したいと思うのは、主に次の場合です:
@Contract
が完璧だと言っているわけではありません。それから遠い。特定のコンテキストでは非常に詳細な分析を行うことはできませんが、これをコードベースに含めることで、ツールでこの種の分析を無料で行うことができます。
_
org.jetbrains.annotations.Contract
_注釈はどのように機能しますか?
これまでの回答は参考になりますが、あなたの質問の「仕事」という言葉が有効に機能しているとは思いません。つまり、IntelliJがアノテーションを実装するために舞台裏で何をしているのかを説明していないので、独自に簡単に独自のコードを作成できます。
以下のソースコードを見ると、_@NotNull
_のように単純に聞こえるかもしれませんが、少し複雑すぎる(または少なくとも冗長な)ように思われるかもしれません。私はあなたに同意します、そして、それは私が一般的に_@Contract
_のような「平易で単純な」節(_@NotNull
_のような)を避け、代わりにJavaDocが私の前提条件を直接避ける1つの理由です。
Igeneralallyは複雑な契約アノテーションを使用しない —この流行の新しい列車をスキップすることで受ける嫌悪感にもかかわらず、ここにいくつかの理由:
考慮すべきいくつかの質問:
_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: <ul>
* <li>An explicit nullness annotation <li>The method overrides a method in a superclass (in which
* case the annotation of the corresponding parameter in the superclass applies) <li> there is a
* default parameter annotation applied to a more tightly nested element. </ul>
* <p/>
* @see https://stackoverflow.com/a/9256595/14731
*/
@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の両方から得られた、ほとんどの重要な(楽観的!)ソースのミックスであり、私のポイントの一部を示しています。
順不同:
そして、結局のところ、私はあなたの元の質問全体にまだ対処できていないかもしれないことに気づきました:)