このコースの目標は、Javaをより効果的に使用できるようにすることです。オブジェクトの作成、並行性、シリアル化、反射、その他の高度な機能など、いくつかの高度なトピックが議論されています。このコースでは、Javaの習熟度の旅を導きます。
1。はじめに
Tiobeプログラミング言語のランキングでは、1995年にSunによって開発されたJava言語は、世界で最も広く使用されているプログラミング言語の1つです。一般的なプログラミング言語として、Java言語は、その強力なツールキットとランタイム環境、シンプルな構文、リッチプラットフォームサポート(一度に書かれ、どこでも実行)、非常に活発なコミュニティサポートにより、ソフトウェア開発エンジニアにとって非常に魅力的です。
この一連の記事では、Javaに関連する高度なコンテンツがカバーされているため、読者はすでに基本的な言語知識を持っていると想定されています。これは完全な参照マニュアルではなく、スキルを次のレベルに引き上げるための徹底的なガイドです。
このコースには、多数のコードスニペットが含まれています。比較するために、他の一部の関係者は、Java 7とJava 8の例を同時に提供します。
2。例の例
オブジェクト指向の言語として、オブジェクトの作成は、おそらくJava言語で最も重要な概念の1つです。コンストラクターは、オブジェクトインスタンスの初期化に重要な役割を果たし、Javaはコンストラクターを定義するさまざまな方法を提供します。
2.1暗黙の(生成)建設方法
Javaは、クラスを定義するときにコンストラクターを宣言することを許可していません。これは、コンストラクターがないことを意味しません。次のクラスの定義を見てみましょう。
パッケージcom.javacodegeeks.advanced.construction; public class noconstuctor {}このクラスはコンストラクターを定義しませんが、Javaコンパイラは暗黙的にそれを生成し、新しいキーワードを使用して新しいオブジェクトインスタンスを作成することができます。
最終noconstructor noconstructorinstance = new noconstructor();
2.2パラメーターレス構造方法
パラメーターレスコンストラクターは、Javaコンパイルを置き換え、明示的な宣言によってコンストラクターを生成する最も簡単な方法です。
パッケージcom.javacodegeeks.advanced.construction; public class noargconstructor {public noargconstructor(){// constructor body here}}}新しいキーワードを使用して新しいオブジェクトインスタンスを作成すると、上記のコンストラクターが呼び出されます。
2.3パラメーターのような構造方法
パラメーター構造方法は最も興味深く広く使用されており、新しいインスタンスの作成はパラメーターを指定することでカスタマイズされます。次の例では、2つのパラメーターを持つコンストラクターを定義します。
パッケージcom.javacodegeeks.advanced.construction; public class constructorwitharguments {public constructorwithargument(final string arg1、final string arg2){// constructor body}}}このシナリオでは、新しいキーワードを使用してインスタンスを作成する場合、構築方法で定義された2つのパラメーターを同時に提供する必要があります。
final constructorwitharguments constructorwitharguments = new constructorwitharguments( "arg1"、 "arg2");
興味深いことに、コンストラクターはこのキーワードを介して互いに呼び出すことができます。実際には、これを使用してコードの重複を減らし、オブジェクトに基づいて単一の初期化エントリを持つことにより、複数のコンストラクターをチェーンすることをお勧めします。例として、次のコードは、パラメーターが1つだけのコンストラクターを定義します。
public constructorwitharguments(final string arg1){this(arg1、null);}2.4コードブロックを初期化します
メソッドの構築に加えて、Javaはコードブロックを初期化して初期化するロジックも提供します。この使用法はまれですが、それについてもっと知ることは有害ではありません。
パッケージcom.javacodegeeks.advanced.construction; public class initializationblock {{//初期化コード}}}}一方、コードブロックの初期化は、パラメーターのない暗黙の構築方法と見なすこともできます。特定のクラスでは、複数の初期化コードブロックを定義でき、次のコードに示すように、実行時にコード内にある順序で呼び出されます。
パッケージcom.javacodegeeks.advanced.construction; public class initializationblocks {{// initialization code here} {//初期化コード}}}実際に初期化するコードブロックは、コンストラクターを交換することではありませんが、同時に表示される可能性があります。ただし、Constructor Method Callがまもなく行われる前に、初期化コードが実行されることを忘れないでください。
パッケージcom.javacodegeeks.advanced.construction; public class initializationblockandConstructor {{//初期化コード} public initializationblockandConstructor(){}}2.5デフォルト値の構築を確認します
Javaは明確な初期化保証を提供し、プログラマーは初期化の結果を直接使用できます。初期化されたインスタンスとクラス変数(statics)は、対応するデフォルト値に自動的に初期化されます。
デフォルト値を入力します
Booleanfalse
byte0
Short0
int0
long0l
char/u0000
float0.0f
Double0.0d
オブジェクトリファレンスnull
表1
次の例を使用して、上記の表のデフォルト値を確認します。
パッケージcom.javacodegeeks.advanced.construction; public class initial withdefaults {private boolean booleanmember;プライベートバイトバイト。プライベートショートショートメンバー。 Private int mmenme;プライベートロングロングメンバー。プライベートチャーチャームバー;プライベートフロートフロートメンバー。プライベートダブルメンバー。プライベートオブジェクト参照メンバー。 public initializationWithDefaults(){system.out.println( "booleanmember =" + booleanmember); system.out.println( "bytemember =" + bytemember); system.out.println( "shortmember =" + shortmember); system.out.println( "intmember =" + intmember); system.out.println( "longmember =" + longmember); System.out.println( "charmember =" + character.codepointat(new char [] {charmember}、0)); system.out.println( "floatmember =" + floatmember); system.out.println( "Doublemberm =" + doublemberm); system.out.println( "参照Member =" + referencemember); }}新しいキーワードを使用してオブジェクトをインスタンス化した後:
最終初期化withdefaults initializationwithdefaults = new initializationWithDefaults()、
次のように、コンソールの出力の結果を確認できます。
booleanmember = falseBytemember = 0shortmember = 0intmember = 0longmember = 0charmember = 0floatmember = 0.0doublemberm = 0.0Referencemember = null
2.6可視性
コンストラクターはJavaの可視性ルールに従い、アクセス制御修飾子を介して他のクラスでコンストラクターを呼び出すことができるかどうかを判断できます。
モディファイアパッケージの可視性サブクラス可視性パブリックの可視性
パブリティ可視可視可視可視可視
保護されている可視性があり、可視的に見えないように見えます
<モディファイアなし>見える、見えない、見えない
プライベートに見えない目に見えない見えない表2
2.7ゴミリサイクル
Java(JVM To precise)には、自動ゴミ収集メカニズムがあります。簡単に言えば、新しいオブジェクトが作成されたときに、その内在性を自動的に割り当てます。その後、オブジェクトがもはや参照されなくなると、それらは自動的に破壊され、対応するメモリがリサイクルされます。
Java Garbage Collectionは、世代のリサイクルメカニズムを採用しており、「ほとんどのオブジェクトには短い寿命がある」という仮定に基づいています(つまり、オブジェクトが作成された直後に唱えられないため、安全に破壊することができます)。ほとんどのプログラマーは、Javaでのオブジェクトの作成は非常に非効率的であると習慣的に信じているため、可能な限り新しいオブジェクトの作成を避ける必要があります。実際、この理解は間違っています。 Javaでオブジェクトを作成するオーバーヘッドは、非常に低く、高速です。実際の世代の巨大なオーバーヘッドは不必要な長期生存オブジェクトであるため、最終的には老年に移住し、世界の停止が発生します。
2.8オブジェクトファイナライザー
建設方法とオブジェクトの初期化に関連するトピックについて話しましたが、それらのネガティブな側面であるオブジェクトの破壊については言及していません。主に、Javaがゴミ収集メカニズムを使用してオブジェクトのライフサイクルを管理し、不要なオブジェクトを破壊し、必要なメモリを解放することがガベージコレクションの責任になるためです。
ただし、Javaは、Destructor Finalizerと同様の別の機能を提供します。これは、複数のリソースをクリーンアップする責任を想定しています。ファイナライザーは一般に危険なものと見なされます(さまざまな副作用やパフォーマンスの問題をもたらすことができるためです)。通常、ファイナルライザーは必要ありませんので、それを避けるようにしてください(多数のネイティブオブジェクトを含むまれなシナリオを除く)。 Java 7で導入されたリソース付きのTry-Resourcesの構文とオートクロー可能なインターフェイスは、ファイナライザーの代替として使用でき、次の簡潔なコードを書くことができます。
try(final inputstream in = files.newinputStream(path)){//ここにコード}3。静的初期化
上記では、クラスインスタンスの構築と初期化について学びました。さらに、Javaは、静的初期化と呼ばれるクラスレベルの初期化構造もサポートしています。静的初期化は、追加の静的キーワードの変更があることを除いて、上記の初期化コードブロックに似ています。静的初期化は、クラスがロードされたときにのみ実行されることに注意する必要があります。例は次のとおりです。
コードブロックの初期化と同様に、クラスで複数の静的初期化ブロックを定義でき、クラス内の位置は、初期化時に実行される順序を決定します。例は次のとおりです。
パッケージcom.javacodegeeks.advanced.construction; public class staticInitializationblocks {static {// static初期化コードはここに} static {// static初期化コード}}}}静的初期化ブロックは、並行して実行される複数のスレッドによってトリガーできるため(クラスが最初にロードされる場合)、JVMランタイムは、初期化されたコードがスレッドに安全な方法で1回だけ実行されることを保証します。
4。コンストラクターモード
長年にわたって、さまざまな理解しやすいコンストラクター(作成者)パターンがJavaコミュニティに紹介されてきました。以下に、より人気のあるもののいくつかを学びます:Singletonモード、補助クラスモード、工場モード、依存関係噴射(コントロール反転とも呼ばれます)。
4.1シングルトンモード
シングルトンは長い歴史ですが、ソフトウェア開発コミュニティでは物議を醸すモデルです。 Singletonパターンのコアコンセプトは、特定のクラスがいつでも1つのオブジェクトのみが作成されるようにすることです。簡単に聞こえますが、正しい方法でセーフでオブジェクトを作成する方法について多くの議論があります。次のコードは、シングルトンパターンの実装の単純なバージョンを示しています。
パッケージcom.javacodegeeks.advanced.construction.patterns; public class naivesingingleton {private static naivesingletonインスタンス; private naivesingleton(){} public static naivesingleton getInstance(){if(instance == null){instance = new naivesingleton(); } returnインスタンス; }}上記のコードには少なくとも1つの問題があります。複数のオブジェクトをマルチスレッドの並行性シナリオで作成できます。実装する合理的な方法(遅延荷重ではない)は、クラスの静的 `finalのプロパティを使用することです。次のように:
class.package com.javacodegeeks.advanced.construction.patterns; public class eagersingleton {private static final eagersingleton instance = new eagersingleton(); private eagerSingleton(){} public static eagerSingleton getInstance(){return instance; }}貴重なリソースを無駄にしたくない場合、シングルトンオブジェクトが本当に必要な場合にのみ作成されたい場合は、明示的な同期方法を使用する必要があります。この方法では、マルチスレッド環境での並行性を低下させる可能性があります(Javaの同時性の詳細については、Java Advanced 9-Conurrency Best Practicesで説明します)。
パッケージcom.javacodegeeks.advanced.construction.patterns; public class lazysingleton {private static lazysingleton instance; private lazySingleton(){} public static同期LazySingleton getInstance(){if(instance == null){instance = new LazySingleton(); } returnインスタンス; }}現在、シングルトンのパターンは、コードがテストしやすくなるため、多くのシナリオではもはや良い選択とは見なされていません。さらに、依存関係噴射モードの生成により、シングルトンモードも不要になります。
4.2ツール/補助クラス
ツールクラス/ヘルプクラスパターンは、Java開発者の間で非常に人気があります。その中心的な概念は、非粘性化クラス(プライベートコンストラクターを宣言することにより)、オプションの最終的な最終クラスを使用することです(宣言の詳細は、Java Advanced 3ClassおよびInterface Designで紹介されます)キーワードと静的メソッド。例は次のとおりです。
パッケージcom.javacodegeeks.advanced.construction.patterns; public final class helperclass {private helperclass(){} public static void helpermethod1(){// method body} public static void helpermethod2(){// method body}}}}多くの経験豊富な開発者は、このパターンがツールクラスをさまざまな無関係な方法のコンテナにすると考えています。一部の方法には適切な配置はありませんが、他のクラスで使用する必要があるため、それらは誤ってツールクラスに配置されます。この設計は、ほとんどのシナリオでも避ける必要があります。コードを明確かつ簡潔に保つためのより良い方法が常にあります。
4.3工場モデル
ファクトリーモデルは、開発者にとって非常に強力なツールであることが証明されており、Javaに実装する多くの方法があります。工場の方法と抽象的な工場です。最も簡単な例は、静的方法を使用して、次のように特定のクラス(工場法)のインスタンスを返すことです。
パッケージcom.javacodegeeks.advanced.construction.patterns; public class book {private book(final string title){} public static book newbook(final string title){return new book(title); }}この方法を使用すると、コードの読みやすさが向上する可能性がありますが、Newbook Factory Methodにより豊富なシナリオを提供することが困難であることは議論の余地があります。工場パターンを実装する別の方法は、インターフェイスまたは抽象クラス(抽象工場)を使用することです。次のように、工場インターフェイスを定義します。
public interface bookfactory {book newbook();}画像ギャラリーに応じて、さまざまなニューブックの実装を使用できます。
パブリッククラスライブラリはBookFactoryを実装しています{@Override Public Book newbook(){return new Paperbook(); }} public class Kindlelibraryはbookfactory {@override public book newbook(){return new Kindlebook(); }}現在、BookFactoryのさまざまな実装は、特定の本の違いをブロックしますが、一般的なNewBookメソッドを提供しています。
4.4依存関係注射
依存関係の注入(コントロール反転とも呼ばれます)は、クラス設計者によって優れた設計プラクティスと見なされます。一部のクラスインスタンスは、他のクラスのインスタンスに依存する場合、インスタンス自体によって作成されるのではなく、コンストラクターメソッド(またはセッターメソッド、ポリシーなど)を介して依存する(挿入)(注入)する必要があります。次のコードを見てみましょう。
パッケージcom.javacodegeeks.advanced.construction.patterns; import java.text.dateformat; import java.util.date; public class依存関係{private final dateformat format = dateformat.getDateInstance(); public String Format(最終日付){return format.format(date); }}従属クラスには、DateFormatクラスのインスタンスが必要であり、オブジェクトをインスタンス化するときにdateFormat.getDateInstance()によって取得されます。より良い方法は、メソッドのパラメーターを構築することにより、同じことを行う必要があります。
パッケージcom.javacodegeeks.advanced.construction.patterns; import java.text.dateformat; import java.util.date; public class depentent {private final dateformatフォーマット; Public Dependent(final DateFormat Format){this.format = format; } public String Format(最終日付){return format.format(date); }}上記の例では、クラスインスタンスのすべての依存関係が外部から提供されているため、簡単に微調整しやすく、テストコードを簡単に記述できます。