IntelliJ IDEAを使用せずにJavaでNPEヘルを倒す

免責事項


最初に、材料が登場したのは、私がインディアンの同僚にnull分析とは何か、それがどれほど優れているか、なぜ企業の怠inessを今すぐ克服してプロジェクトでこの分析を使用する必要があるのか​​をすばやく説明したかったためです IDEを参照せずに主題に関する完全な体系化された情報を含む記事はなかったので、私は自分でそれを書かなければなりませんでした。 そして、完全な体系化の結果としてはうまくいきませんでしたが、私はまだ素材をより多くの聴衆と共有したいと思っていました。 最小限のテキストと多くの画像があります。

第二に、リソースにはすでにIntelliJ IDEAに捧げられた素晴らしい記事 tr1cksがあり IDEAは非常に良い、Eclipseは貧しい人のためのすでに強い印象を補強しています(これは言い換えになります)。 バランスを取るために、Eclipseに焦点を当てます。

FindBugsプロジェクトアノテーション( JSR 305アノテーションとも呼ばれます)を使用するのは、特定の開発環境へのバインディングがないためです(ファンはorg.eclipse.jdt.annotation.*を使用できますorg.eclipse.jdt.annotation.*およびorg.jetbrains.annotations.* ) Maven Centralで利用できるという事実によります 。 Mavenを使用している場合は、次を<dependencies/>セクションに追加するだけです。

 <dependency> <groupId>com.google.code.findbugs</groupId> <artifactId>jsr305</artifactId> <version>3.0.0</version> </dependency> 

念のため、予約をします

  @Nonnull public String getName() { // ... } 

そして

  public @Nonnull String getName() { // ... } 

-これらは完全に同等の2つの構造ですが、場合によっては、取得したバイトコードの2つのバリアントが正確に1バイト異なる可能性があります(ところで、なぜだと思いますか?)

日食


以下はすべてEclipse 4.4(Luna)でテスト済みです。 同時に、もし私の記憶が私に役立っているなら、説明された機能はすでに3.8(そしておそらくそれ以前)に存在していました。

カスタマイズ




偽陽性の診断


診断が間違っていると幸せになる人はほとんどいません。 幸いなことに、「医師、あなたは酔って、他の誰かの血を分析しました!」と言う機会があります。

問題


この写真は、Eclipseが(もちろん、シングルスレッドのシナリオでは) hashCode()呼び出しの時点でフィールドfieldnullにできないことを判断できないことを示しています。


はい、もちろん、メソッド全体を@SuppressWarnings("null")でマークでき@SuppressWarnings("null")が、これはnull分析のすべての利点を無効にします。

回避策0


assert追加:


回避策1


長いですが、可能です。 フィールド値をローカル変数にプルし、 @Nonnullとしてマークしてから作業します。


落とし穴


Java 1.8以降では、新しいタイプのメタデータ( タイプアノテーションJSR 308を参照))がサポートされているため、 @Targetを明示的に指定するにはアノテーションが必要です。 FindBugsアノテーションはこの要件を満たしていません。 したがって、最大4.4 (Luna)およびJava 1.8を含むEclipseを使用する場合、FindBugs注釈を使用したnull分析は機能しません( バグ#435805 )。 一般に、この場合、Eclipse 4.5 (Mars)に切り替える方が適切です。

ホームリーディング




アイデア


IntelliJ IDEAは、時間の初めからnull分析をサポートしているようです( Constant条件と例外@ NotNull / @Nullable問題をチェックする )。




すばらしいのは、JSR 305を含む多くの適切な注釈が「すぐに使える」環境ですぐにわかることです。


唯一の残念な点は、Eclipseとは異なり、パッケージ全体の注釈( @NonNullByDefault@ParametersAreNonnullByDefault )がサポートされていないことです。

更新する


アセンブリ138.1372( IDEA-125281 )以降、パッケージレベルで@ParametersAreNonnullByDefaultおよび@ParametersAreNullableByDefaultが認識および分析されますが、設定には表示されません( Borzのおかげです )。 さらに、機能はIDEA 13.1.6(ビルド135.1306)に存在するようです。

Netbeans


NetBeansは7.3以降、 null分析をサポートしていnull 。次を参照してください。 英語の 記事

備考


IDEだけでなくFindBugsも使用する場合、 nullを返す可能性のあるメソッドは@Nullableとしてマークするだけでなく、 @Nullableとしてマークする必要があります@CheckForNull@CheckForNull場合にのみ「落ち着きます」。

素敵なボーナス nishtyaki副作用


これは、このトピックからの叙情的な余談ですが、分析の導入がProject Xにもたらした当面の利点について説明しています。より正確には、単体テストの落とし穴を特定するのに役立ちました。

むかしむかし、落ちないが、あまり巧妙に書かれていないテストがありました。 はい、あなたは間違っていませんでした。これはJUnit 3です。

 public void test() throws Exception { final Calendar calendar = myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); assertEquals(1997, year); assertEquals("1.1", System.getProperty("java.specification.version")); } 

わずか数年が経過し、テストが失敗したことがわかりました。 つまり、まだコンパイルされますが、動作しなくなります。 鼻の蚊が変色しないように、テストは「修正」されました。 要するに、誰も何も気づきませんでした:

 public void test() throws Exception { final Calendar calendar = myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); // assertEquals(1997, year); // assertEquals("1.1", System.getProperty("java.specification.version")); } 

数年後、コンパイルも停止し、適切な統計が必要でした。 テストは再び修復されました。 NPEを取り除くことは不可能であり、大量のコードをスローすることが注目を集めるため、古いテストは偽装され、目を回避するために2番目の遅延を伴う新しいテストが導入されました。

 public void test() throws Exception { Thread.sleep(1000); } public void _test() throws Exception { final Calendar calendar = null; //myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); // assertEquals(1997, year); // assertEquals("1.1", System.getProperty("java.specification.version")); } 

結論は?

レガシーコードの場合でも、 Nullポインターアクセス潜在的なNULLポインターアクセスのレベルを「エラー」に上げることが理にかなっている場合があります。 特にレガシーコードの場合。 20年前に文字通りゼロから製品を作成し、 10年前に一部のGoogleやAmazonに成功した「バイソン」の能力を想像することさえできません。

願い


読者の中にC#を使用している人がいる場合、コメントしてください-Nullableなどの素晴らしいものの存在に照らしてC#に関連する問題はありますか?そうであれば、どのように解決されますか?

Source: https://habr.com/ru/post/J204518/


All Articles