注: 私はこのガイドのバージョン 2 に取り組んでおり、あなたの助けが必要です。次のバージョンで何をすべきかについてフィードバックをお送りいただくには、このフォームを使用してください。ありがとう!
Java は最も人気のあるプログラミング言語の 1 つですが、Java の使用を楽しんでいる人はいないようです。 Java は実際には優れたプログラミング言語であり、最近 Java 8 が登場したため、Java をより良く使用するためのライブラリ、プラクティス、およびツールのリストを作成することにしました。 「より良い」というのは主観的なものなので、一度にすべてを使おうとするのではなく、自分に響く部分を取り出して使うことをお勧めします。追加を提案するプル リクエストを遠慮なく送信してください。
この記事はもともと私のブログに投稿されたものです。
他の言語で読む: 英語、简体中文
従来、Java は非常に冗長なエンタープライズ JavaBean スタイルでプログラムされていました。新しいスタイルは、よりクリーンで正確で、目にも優しいものになっています。
私たちがプログラマーとして行う最も単純なことの 1 つは、データの受け渡しです。これを行う従来の方法は、JavaBean を定義することです。
public class DataHolder {
private String data ;
public DataHolder () {
}
public void setData ( String data ) {
this . data = data ;
}
public String getData () {
return this . data ;
}
}
これは冗長で無駄です。たとえ IDE がこのコードを自動的に生成したとしても、それは無駄です。だから、これはやめてください。
代わりに、私は単にデータを保持するクラスを記述する C 構造体のスタイルを好みます。
public class DataHolder {
public final String data ;
public DataHolder ( String data ) {
this . data = data ;
}
}
これにより、コード行数が半分に減ります。さらに、このクラスは拡張しない限り不変であるため、変更できないことがわかっているため、推論が容易になります。
Map や List など、簡単に変更できるオブジェクトを保存している場合は、代わりに ImmutableMap または ImmutableList を使用する必要があります。これについては、不変性に関するセクションで説明します。
構造体を構築したいかなり複雑なオブジェクトがある場合は、Builder パターンを検討してください。
オブジェクトを構築する静的内部クラスを作成します。可変状態を使用しますが、build を呼び出すとすぐに、不変オブジェクトが生成されます。
もっと複雑なDataHolderがあると想像してください。そのビルダーは次のようになります。
public class ComplicatedDataHolder {
public final String data ;
public final int num ;
// lots more fields and a constructor
public static class Builder {
private String data ;
private int num ;
public Builder data ( String data ) {
this . data = data ;
return this ;
}
public Builder num ( int num ) {
this . num = num ;
return this ;
}
public ComplicatedDataHolder build () {
return new ComplicatedDataHolder ( data , num ); // etc
}
}
}
次に、それを使用するには:
final ComplicatedDataHolder cdh = new ComplicatedDataHolder . Builder ()
. data ( "set this" )
. num ( 523 )
. build ();
ビルダーのより良い例は他にもありますが、これはそれがどのようなものかを知るためのものです。これにより、私たちが避けようとしていた多くの定型文が使用されることになりますが、不変のオブジェクトと非常に滑らかなインターフェイスが得られます。
ビルダー オブジェクトを手動で作成する代わりに、ビルダーの生成に役立つ多くのライブラリの 1 つを使用することを検討してください。
多くの不変オブジェクトを手動で作成する場合は、アノテーション プロセッサを使用してそれらをインターフェイスから自動的に生成することを検討してください。これにより定型コードが最小限に抑えられ、バグの可能性が減り、不変性が促進されます。通常の Java コーディング パターンに関するいくつかの問題についての興味深い説明については、このプレゼンテーションを参照してください。
優れたコード生成ライブラリには、Google の auto-value や Lombok など、不変のものもあります。
チェック例外を使用する場合は、注意して使用する必要があります。ユーザーは多くの try/catch ブロックを追加し、独自の例外をラップする必要があります。代わりに、例外を RuntimeException を拡張することをお勧めします。これにより、ユーザーは、毎回スローされる例外の処理や宣言を強制してコードを汚染するのではなく、希望する方法で例外を処理できるようになります。
気の利いたトリックの 1 つは、メソッドの throws 宣言に RuntimeExceptions を入れることです。これはコンパイラには影響しませんが、これらの例外がスローされる可能性があることをドキュメントを通じてユーザーに通知します。
これは Java セクションというよりソフトウェア エンジニアリング セクションに近いですが、テスト可能なソフトウェアを作成する最良の方法の 1 つは依存関係注入 (DI) を使用することです。 Java は OO 設計を強く推奨しているため、テスト可能なソフトウェアを作成するには DI を使用する必要があります。
Java では、これは通常 Spring Framework を使用して行われます。コードベースの配線または XML 構成ベースの配線のいずれかがあります。 XML 構成を使用する場合、Spring は XML ベースの構成形式であるため、過度に使用しないことが重要です。 XML にはロジックや制御構造がまったく存在してはなりません。依存関係のみを注入する必要があります。
Spring を使用する代わりに、Google および Square の Dagger ライブラリまたは Google の Guice を使用することをお勧めします。 Spring の XML 構成ファイル形式は使用せず、代わりに注入ロジックを注釈とコードに配置します。
できる限り null の使用を避けるようにしてください。空のコレクションを返す必要がある場合は、null コレクションを返さないでください。 null を使用する場合は、@Nullable アノテーションを検討してください。 IntelliJ IDEA には @Nullable アノテーションのサポートが組み込まれています。
null を使用しない理由については、「コンピューター サイエンスの最悪の間違い」を参照してください。
Java 8 を使用している場合は、優れた新しい Optional タイプを使用できます。値が存在する場合と存在しない場合は、次のようにそれをOptionalクラスでラップします。
public class FooWidget {
private final String data ;
private final Optional < Bar > bar ;
public FooWidget ( String data ) {
this ( data , Optional . empty ());
}
public FooWidget ( String data , Optional < Bar > bar ) {
this . data = data ;
this . bar = bar ;
}
public Optional < Bar > getBar () {
return bar ;
}
}
したがって、データがnull になることはありませんが、 bar が存在する場合と存在しない場合があることは明らかです。 Optional にはisPresentのようなメソッドがあり、単にnull をチェックするのとあまり変わらないように感じるかもしれません。ただし、次のようなステートメントを書くことができます。
final Optional < FooWidget > fooWidget = maybeGetFooWidget ();
final Baz baz = fooWidget . flatMap ( FooWidget :: getBar )
. flatMap ( BarWidget :: getBaz )
. orElse ( defaultBaz );
これは、null チェックの連鎖よりもはるかに優れています。 Optional を使用する唯一の欠点は、標準ライブラリには適切な Optional サポートがないため、そこでも null を処理する必要があることです。
特別な理由がない限り、変数、クラス、コレクションは不変でなければなりません。
変数は、 finalを使用して不変にすることができます。
final FooWidget fooWidget ;
if ( condition ()) {
fooWidget = getWidget ();
} else {
try {
fooWidget = cachedFooWidget . get ();
} catch ( CachingException e ) {
log . error ( "Couldn't get cached value" , e );
throw e ;
}
}
// fooWidget is guaranteed to be set here
これで、fooWidget が誤って再割り当てされることがなくなります。 Finalキーワードは、if/else ブロックおよび try/catch ブロックで機能します。もちろん、 fooWidget自体が不変でない場合は、簡単に変更できます。
コレクションでは、可能な限り、Guava ImmutableMap、ImmutableList、または ImmutableSet クラスを使用する必要があります。これらにはビルダーがあり、それらを動的に構築し、build メソッドを呼び出して不変のマークを付けることができます。
クラスを不変にするには、フィールドを不変として宣言し ( finalを介して)、不変のコレクションを使用する必要があります。必要に応じて、クラス自体をFinal にして、クラスを拡張したり変更可能にしたりできないようにすることができます。
Util クラスに多数のメソッドを追加している場合は注意してください。
public class MiscUtil {
public static String frobnicateString ( String base , int times ) {
// ... etc
}
public static void throwIfCondition ( boolean condition , String msg ) {
// ... etc
}
}
これらのクラスは、そこに含まれるメソッドが実際には 1 つの場所に属していないため、最初は魅力的に見えます。したがって、コードの再利用の名の下に、それらをすべてここに放り込みます。
治療法は病気よりも悪い。これらのクラスを適切な場所に配置し、積極的にリファクタリングします。クラス、パッケージ、またはライブラリには、「MiscUtils」や「ExtrasLibrary」など、あまりにも一般的な名前を付けないでください。これにより、無関係なコードをそこにダンプすることが奨励されます。
書式設定は、ほとんどのプログラマが考えているほど重要ではありません。一貫性はあなたが自分の作品に関心を持っていることを示しており、他の人が読むのに役立ちますか?絶対に。ただし、「一致する」ように if ブロックにスペースを追加する作業に 1 日も費やさないようにしましょう。
コードのフォーマット ガイドがどうしても必要な場合は、Google の Java スタイル ガイドを強くお勧めします。このガイドの最も優れた部分は、「プログラミングの実践」セクションです。間違いなく一読の価値があります。
ユーザー向けのコードを文書化することは重要です。これは、例を使用し、変数、メソッド、クラスの賢明な説明を使用することを意味します。
この結果、文書化する必要のないものは文書化しないことになります。議論の内容について何も言うことがない場合、またはそれが明白な場合は、それを文書化しないでください。定型的なドキュメントは、ドキュメントがあるかのようにユーザーを騙すため、まったくドキュメントがないよりも悪いです。
Java 8 には優れたストリームとラムダ構文があります。次のようなコードを書くことができます。
final List < String > filtered = list . stream ()
. filter ( s -> s . startsWith ( "s" ))
. map ( s -> s . toUpperCase ())
. collect ( Collectors . toList ());
代わりに:
final List < String > filtered = new ArrayList <>();
for ( String str : list ) {
if ( str . startsWith ( "s" ) {
filtered . add ( str . toUpperCase ());
}
}
これにより、より流暢で読みやすいコードを作成できるようになります。
Java を適切にデプロイするのは少し難しい場合があります。現在、Java をデプロイするには主に 2 つの方法があります。フレームワークを使用するか、より柔軟な自社開発のソリューションを使用します。
Java の導入は簡単ではないため、役立つフレームワークが作成されています。最高の 2 つは Dropwizard と Spring Boot です。 Play フレームワークも、これらのデプロイメント フレームワークの 1 つと考えることができます。
これらはすべて、コードを公開する際の障壁を低くしようとしています。これらは、Java を初めて使用する場合、または作業を迅速に完了する必要がある場合に特に役立ちます。単一の JAR デプロイメントは、複雑な WAR または EAR デプロイメントよりも簡単です。
ただし、柔軟性がやや低く、かなり意見が偏っている場合があるため、フレームワークの開発者が行った選択にプロジェクトが適合しない場合は、より手動で調整した構成に移行する必要があります。
良い代替手段: Gradle。
Maven は今でもテストを構築、パッケージ化、実行するための標準ツールです。 Gradle などの代替手段はありますが、Maven ほど採用されていません。 Maven を初めて使用する場合は、Maven by Example から始める必要があります。
私は、使用したいすべての外部依存関係を含むルート POM を用意したいと考えています。このような感じになります。このルート POM には外部依存関係が 1 つだけありますが、製品が十分に大きい場合は、数十の外部依存関係があります。ルート POM は、それ自体がバージョン管理されたプロジェクトであり、他の Java プロジェクトと同様にリリースされる必要があります。
外部依存関係の変更ごとにルート POM にタグを付けるのは多すぎると思うなら、プロジェクト間の依存関係エラーを追跡するのに 1 週間も無駄にはしていません。
すべての Maven プロジェクトには、ルート POM とそのすべてのバージョン情報が含まれます。このようにして、会社が選択した各外部依存関係のバージョンと、すべての正しい Maven プラグインを取得できます。外部依存関係を取り込む必要がある場合は、次のように機能します。
< dependencies >
< dependency >
< groupId >org.third.party</ groupId >
< artifactId >some-artifact</ artifactId >
</ dependency >
</ dependencies >
内部依存関係が必要な場合は、各プロジェクトの個別の依存関係を管理する必要があります。セクション。そうしないと、ルート POM のバージョン番号を正常に保つことが困難になります。
Java の最も優れた点の 1 つは、あらゆる機能を備えた大量のサードパーティ ライブラリがあることです。基本的にすべての API またはツールキットには Java SDK が含まれており、Maven を使用して簡単に取り込むことができます。
そして、それらの Java ライブラリ自体は、他のライブラリの特定のバージョンに依存します。十分なライブラリを取り込むと、次のようなバージョンの競合が発生します。
Foo library depends on Bar library v1.0
Widget library depends on Bar library v0.9
どのバージョンがプロジェクトに取り込まれますか?
Maven 依存関係収束プラグインでは、依存関係が同じバージョンを使用していない場合、ビルドでエラーが発生します。この場合、競合を解決するには 2 つのオプションがあります。
どちらを選択するかは状況によって異なります。1 つのプロジェクトのバージョンを追跡したい場合は、除外するのが理にかなっています。一方、明示的にしたい場合は、バージョンを選択できますが、他の依存関係を更新するときにバージョンも更新する必要があります。
明らかに、SNAPSHOT バージョンを継続的にビルドし、git タグに基づいてビルドをタグ付けする、ある種の継続的統合サーバーが必要です。
Jenkins と Travis-CI は自然な選択です。
コード カバレッジは便利で、Cobertura には優れた Maven プラグインと CI サポートがあります。 Java 用のコード カバレッジ ツールは他にもありますが、私は Cobertura を使用しました。
作成した JAR、WAR、EAR を配置する場所が必要なので、リポジトリが必要になります。
一般的な選択肢は Artifactory と Nexus です。どちらも機能しますが、それぞれ長所と短所があります。
独自の Artifactory/Nexus インストールを用意し、そこに依存関係をミラーリングする必要があります。これにより、上流の Maven リポジトリの一部がダウンしたためにビルドが中断されるのを防ぐことができます。
コードがコンパイルされ、リポジトリがセットアップされたので、コードを開発環境に取り出し、最終的には実稼働環境にプッシュする必要があります。これを自動化すると長期的に利益が得られるため、ここでケチらないでください。
Chef、Puppet、Ansible が一般的な選択肢です。私は Squadron と呼ばれる代替案を書きました。もちろん、代替案よりも正しく理解するのが簡単なので、ぜひチェックしてみてください。
どのツールを選択する場合でも、デプロイメントを自動化することを忘れないでください。
おそらく Java の最大の特徴は、豊富なライブラリがあることです。これは、最も大規模なグループに適用できると思われるライブラリの小規模なコレクションです。
Java の標準ライブラリは、かつては驚くべき進歩を遂げていましたが、現在ではいくつかの重要な機能が欠けているように見えます。
Apache Commons プロジェクトには、便利なライブラリが多数あります。
Commons Codec には、Base64 および 16 進文字列の便利なエンコード/デコード方法が多数あります。それらを書き直すことに時間を無駄にしないでください。
Commons Lang は、文字列の操作と作成、文字セット、およびさまざまなユーティリティ メソッドの頼りになるライブラリです。
Commons IO には、必要なファイル関連のメソッドがすべて揃っています。 FileUtils.copyDirectory、FileUtils.writeStringToFile、IOUtils.readLines などが含まれます。
Guava は、Java に不足しているものを解決する Google の優れたライブラリです。このライブラリの気に入っている点をすべて抽出するのはほとんど難しいですが、試してみるつもりです。
キャッシュは、ネットワーク アクセス、ディスク アクセス、メモ化関数などをキャッシュするために使用できるメモリ内キャッシュを取得する簡単な方法です。 Guava にキャッシュの構築方法を指示する CacheBuilder を実装するだけで準備は完了です。
不変のコレクション。 ImmutableMap、ImmutableList、または好みに応じて ImmutableSortedMultiSet など、たくさんあります。
私は、Guava の方法で可変コレクションを書くのも好きです。
// Instead of
final Map < String , Widget > map = new HashMap <>();
// You can use
final Map < String , Widget > map = Maps . newHashMap ();
リスト、マップ、セットなどの静的クラスがあります。よりクリーンで読みやすくなりました。
Java 6 または 7 に行き詰まっている場合は、フィルターや変換などのメソッドを備えた Collections2 クラスを使用できます。これらを使用すると、Java 8 のストリーム サポートなしで流暢なコードを書くことができます。
Guava には、区切り記号で文字列を結合するJoinerや割り込みを無視して処理するクラスなど、単純なものもあります。
Google の Gson ライブラリは、シンプルで高速な JSON 解析ライブラリです。次のように動作します。
final Gson gson = new Gson ();
final String json = gson . toJson ( fooWidget );
final FooWidget newFooWidget = gson . fromJson ( json , FooWidget . class );
とても簡単で、楽しく作業できます。 Gson ユーザー ガイドにはさらに多くの例が記載されています。
Java に関して私がずっと抱えている不満の 1 つは、Java には標準ライブラリにタプルが組み込まれていないことです。幸いなことに、Java タプル プロジェクトはそれを修正します。
使い方は簡単で、うまく機能します。
Pair < String , Integer > func ( String input ) {
// something...
return Pair . with ( stringResult , intResult );
}
Javaslang は関数ライブラリであり、Java 8 の一部であるべき欠落している機能を追加するように設計されています。これらの機能の一部は次のとおりです。
オリジナルの Java コレクションに依存する Java ライブラリがいくつかあります。これらは、オブジェクト指向に重点を置いて作成され、変更可能であるように設計されたクラスとの互換性を維持するために制限されています。 Java 用の Javaslang コレクションは、Haskell、Clojure、Scala からインスピレーションを得た、まったく新しいものです。これらは機能を重視して作成され、不変のデザインに従っています。
次のようなコードは自動的にスレッド セーフになり、try-catch フリーになります。
// Success/Failure containing the result/exception
public static Try < User > getUser ( int userId ) {
return Try . of (() -> DB . findUser ( userId ))
. recover ( x -> Match . of ( x )
. whenType ( RemoteException . class ). then ( e -> ...)
. whenType ( SQLException . class ). then ( e -> ...));
}
// Thread-safe, reusable collections
public static List < String > sayByeBye () {
return List . of ( "bye, " bye ", "collect" , "mania" )
. map ( String :: toUpperCase )
. intersperse ( " " );
}
Joda-Time は、私が今まで使った中で間違いなく最高の時間ライブラリです。シンプルでわかりやすく、テストも簡単です。他に何をお願いできますか?
これは、まだ Java 8 を使用していない場合にのみ必要です。Java 8 には、面倒ではない独自の新しい時間ライブラリがあるためです。
ロンボク島は興味深い図書館です。アノテーションを使用すると、Java で大きな問題となる定型文を減らすことができます。
クラス変数のセッターとゲッターが必要ですか?単純:
public class Foo {
@ Getter @ Setter private int var ;
}
これで、次のことができるようになります。
final Foo foo = new Foo ();
foo . setVar ( 5 );
他にもたくさんあります。私はまだ Lombok を実稼働環境で使用したことがありませんが、使用するのが待ちきれません。
良い選択肢: ジャージまたはスパーク
Java で RESTful Web サービスを実行するには、JAX-RS とその他すべてという 2 つの主なキャンプがあります。
JAX-RS は従来の方法です。 Jersey などを使用して、アノテーションとインターフェイスおよび実装を組み合わせて Web サービスを形成します。これの優れた点は、インターフェイス クラスだけからクライアントを簡単に作成できることです。
Play フレームワークは、JVM 上の Web サービスとは根本的に異なるものです。ルート ファイルがあり、それらのルートで参照されるクラスを作成します。これは実際には MVC フレームワーク全体ですが、REST Web サービスだけに簡単に使用できます。
Java と Scala の両方で利用できます。 Scala ファーストであるため多少の欠点はありますが、それでも Java で使用するのには適しています。
Python の Flask などのマイクロフレームワークに慣れている場合は、Spark は非常に馴染み深いでしょう。特に Java 8 でうまく機能します。
Java ログ ソリューションはたくさんあります。私のお気に入りは SLF4J です。SLF4J は非常にプラグイン可能で、多くの異なるロギング フレームワークからのログを同時に結合できるからです。 java.util.logging、JCL、log4j を使用する奇妙なプロジェクトをお持ちですか? SLF4Jはそんなあなたにぴったりです。
始めるのに必要なのは 2 ページのマニュアルだけです。
私は SQL が好きなので、重い ORM フレームワークは嫌いです。そのため、たくさんの JDBC テンプレートを作成しましたが、維持するのが少し大変でした。 jOOQ ははるかに優れたソリューションです。
これにより、タイプセーフな方法で Java で SQL を書くことができます。
// Typesafely execute the SQL statement directly with jOOQ
Result < Record3 < String , String , String >> result =
create . select ( BOOK . TITLE , AUTHOR . FIRST_NAME , AUTHOR . LAST_NAME )
. from ( BOOK )
. join ( AUTHOR )
. on ( BOOK . AUTHOR_ID . equal ( AUTHOR . ID ))
. where ( BOOK . PUBLISHED_IN . equal ( 1948 ))
. fetch ();
これと DAO パターンを使用すると、データベース アクセスが簡単になります。
テストはソフトウェアにとって非常に重要です。これらのパッケージはそれを容易にするのに役立ちます。
良い代替案: TestNG。
jUnit については説明の必要はありません。これは、Java の単体テストの標準ツールです。
しかし、おそらく jUnit の可能性を最大限に活用していないでしょう。 jUnit は、パラメーター化されたテスト、定型文を大量に作成するのを防ぐルール、特定のコードをランダムにテストするための理論、および仮定をサポートしています。
依存関係の注入を行った場合、ここで効果が得られます。副作用のあるコード (REST サーバーとの通信など) をモックアウトし、それを呼び出すコードの動作を引き続きアサートします。
jMock は Java の標準モック ツールです。次のようになります。
public class FooWidgetTest {
private Mockery context = new Mockery ();
@ Test
public void basicTest () {
final FooWidgetDependency dep = context . mock ( FooWidgetDependency . class );
context . checking ( new Expectations () {{
oneOf ( dep ). call ( with ( any ( String . class )));
atLeast ( 0 ). of ( dep ). optionalCall ();
}});
final FooWidget foo = new FooWidget ( dep );
Assert . assertTrue ( foo . doThing ());
context . assertIsSatisfied ();
}
}
これにより、jMock 経由でFooWidgetDependencyが設定され、期待値が追加されます。 depのcallメソッドは何らかの String で 1 回呼び出され、 depのOptionalCallメソッドは 0 回以上呼び出されることを想定しています。
同じ依存関係を何度も設定する必要がある場合は、おそらくそれをテスト フィクスチャに入れて、 assertIsSatisfied を@Afterフィクスチャに入れる必要があります。
jUnit でこれを行ったことはありますか?
final List < String > result = some . testMethod ();
assertEquals ( 4 , result . size ());
assertTrue ( result . contains ( "some result" ));
assertTrue ( result . contains ( "some other result" ));
assertFalse ( result . contains ( "shouldn't be here" ));
これは単なる迷惑な定型文です。 AssertJ はこれを解決します。同じコードを次のように変換できます。
assertThat ( some . testMethod ()). hasSize ( 4 )
. contains ( "some result" , "some other result" )
. doesNotContain ( "shouldn't be here" );
この流暢なインターフェイスにより、テストがより読みやすくなります。これ以上何を望むでしょうか?
優れた代替手段: Eclipse と Netbeans
最高の Java IDE は IntelliJ IDEA です。これには素晴らしい機能がたくさんあり、Java の冗長性を実現する主な機能です。オートコンプリートは素晴らしく、検査は一流で、リファクタリング ツールは非常に役立ちます。
私にとっては無料のコミュニティ エディションで十分ですが、Ultimate エディションにはデータベース ツール、Spring Framework のサポート、Chronon などの優れた機能がたくさんあります。
GDB 7 の私のお気に入りの機能の 1 つは、デバッグ中に過去に戻る機能です。 Ultimate エディションを入手すると、Chronon IntelliJ プラグインを使用してこれが可能になります。
変数の履歴、ステップバック、メソッドの履歴などを取得できます。初めて使用するのは少し奇妙ですが、非常に複雑なバグやハイゼンバグなどのデバッグに役立ちます。
良い代替品: DCEVM
継続的統合は、多くの場合、Software-as-a-Service 製品の目標です。コードの変更をライブで確認するためにビルドが完了するのを待つ必要さえなかったらどうなるでしょうか?
それが JRebel のやっていることです。サーバーを JRebel クライアントに接続すると、サーバー上の変更を即座に確認できます。すぐに実験したい場合は、時間を大幅に節約できます。
Java の型システムは非常に弱いです。文字列と実際に正規表現である文字列を区別せず、汚染チェックも行いません。ただし、Checker Framework はこれ以外のことも行います。
@Nullableなどのアノテーションを使用して型をチェックします。独自のアノテーションを定義して、静的分析をさらに強力にすることもできます。
ベスト プラクティスに従っている場合でも、優秀な開発者でも間違いを犯すことがあります。 Java コードを検証してコード内の問題を検出するために使用できるツールが多数あります。以下は、最も人気のあるツールの一部です。これらの多くは、Eclipse や IntelliJ などの一般的な IDE と統合されているため、コード内の間違いをより早く発見できるようになります。
これらのツールを開発中に使用するだけでなく、ビルド段階でも実行することをお勧めします。これらは、Maven や Gradle などのビルド ツールや継続的統合ツールに結び付けることができます。
メモリリークは Java でも発生します。幸いなことに、そのためのツールがあります。これらを修正するために私が使用した最良のツールは、Eclipse Memory Analyzer です。ヒープ ダンプを取得して問題を見つけます。
JVM プロセスのヒープ ダンプを取得するにはいくつかの方法がありますが、私は jmap を使用します。
$ jmap -dump:live,format=b,file=heapdump.hprof -F 8152
Attaching to process ID 8152, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 23.25-b01
Dumping heap to heapdump.hprof ...
... snip ...
Heap dump file created
次に、Memory Analyzer でheapdump.hprofファイルを開いて、何が起こっているかをすぐに確認できます。
Java マスターになるのに役立つリソース。