Javaでプロパティ、メソッド、クラスを宣言する場合、キーワードファイナルを使用して変更できます。最終変数は定数であり、1回しか割り当てられません。最終的な方法は、サブクラスによって書き直すことはできません。最終クラスを継承することはできません。
1。最終メンバー
最終フィールドを宣言すると、オプティマイザーが最適化の決定を改善するのに役立ちます。これは、コンパイラがフィールドの値が変更されないことを知っている場合、レジスタの値を安全にキャッシュできるためです。また、最終フィールドは、コンパイラにフィールドを読み取り専用に強制することにより、追加のレベルのセキュリティを提供します。
1.1最終メンバーの割り当てについて
1)Javaでは、通常の変数をデフォルトで初期化できます。ただし、最終型の変数を明示的に初期化する必要があります。
2)最終メンバーは、1回しか初めてではありません。
3)最終メンバーは、宣言時に初期化され(定義されたときに最終変数に直接値を割り当てる)、またはコンストラクター内で、他の場所で初期化することはできません。
例1 bat.java
Public Class Bat {Final Double Pi = 3.14; //定義されたときにfinal int iを割り当てます。 //コンストラクターで初期化されるため、ここで最終リスト<バット>リストを割り当てることはできません。 //コンストラクターで初期化されるため、bat()をここに割り当てることはできません{i = 100; list = new LinkedList <bat>(); } bat(int II、list <bat> l){i = ii; list = l; } public static void main(string [] args){bat b = new bat(); b.list.add(new bat()); // bi = 25; // b.list = new ArrayList <bat>(); system.out.println( "i =" + bi + "list type:" + b.list.getClass()); b = new bat(23、new ArrayList <bat>()); b.list.add(new bat()); system.out.println( "i =" + bi + "list type:" + b.list.getClass()); }}
結果:
i = 100リストタイプ:クラスjava.util.linkedlisti = 23リストタイプ:クラスjava.util.arraylist
メインメソッドには、コメントアウトされる2つの声明があります。コメントを削除すると、プログラムはコンパイルできません。これは、Iの値であろうと、リストのタイプであろうと、初期化されると変更できないことを意味します。ただし、Bは、再認証によりIまたはIの値またはリストのタイプを指定できます。
1.2最終参照フィールドの初期化
特にコンストラクターが例外をスローできるオブジェクト参照については、最終フィールドを正しく使用するのは少し面倒です。最終フィールドは各コンストラクターで1回のみ初期化する必要があるため、最終オブジェクトによって参照されるコンストラクターが例外をスローできる場合、コンパイラはフィールドが初期化されていないというエラーを報告する場合があります。コンパイラは一般に、2つのミューテックスコードブランチの各ブランチの初期化(たとえば、... elseブロックの場合)が1回だけ発生することを見つけるのに十分なほどスマートですが、通常は...ブロックをキャッチするのはそれほど「寛容」ではありません。
通常、次のコードには問題があります。
class thingie {public static thingie getDefaultThingie(){return new Thingie(); }} public class foo {private finalthingie thingie; public foo(){try {thingie = new Thingie(); } catch(Exception e){Thingie = Thingie.getDefaultThingie(); //エラー:最終フィールドThingieはすでに割り当てられている可能性があります}}}}
これを変更できます。
パブリッククラスfoo {private finalthingie thingie; public foo(){thingie tempthingie; try {tempthingie = new Thingie(); } catch(例外e){tempthingie = thingie.getDefaultThingie(); } thingie = tempthingie; }}
1.3最終メンバーの使用について
クラス内の変数を定義する場合、その前に最終キーワードを追加します。つまり、この変数が初期化されると、変更できません。ここでの不変性の意味は、その値が基本タイプに不変であり、その参照をオブジェクト変数に対してもはや変更できないことです。ただし、オブジェクト自体を変更でき、Javaはオブジェクトを一定にする方法を提供しません。この制限は、オブジェクトである配列にも適合します。
例2
Private final int val_one = 9; private static final int val_two = 99; public static final int val_three = 999;
VAL_ONEとVAL_TOWはコンパイル時間値を持つ最終的なプリミティブタイプであるため、両方ともコンパイル時間定数として使用でき、有意な違いはありません。 Val_threeは、定数を定義するより典型的な方法です。パブリックとして定義され、パッケージの外で使用できます。 1つのコピーのみを強調する静的として定義されています。それが定数であることを示す最終として定義されています。
マークされた変数ファイナルは定数になりますが、この「定数」はこのクラス内でのみ使用でき、クラスの直接使用はできません。ただし、public staticファイナルを使用して定数をマークすると、この定数はグローバル定数になります(静的と最終の両方のフィールドは、変更できないストレージスペースを占有します)。さらに、この方法で定義された定数は、定義されたときに値を割り当てることができ、他の場所では使用できません。
例3
クラス値{int i; public Value(int i){this.i = i; }} public class finaldata {private static randon rand = new Random();プライベート文字列ID; public finalData(string id){this.id = id; } private final int i4 = rand.nextint(20);静的最終int i5 = rand.nextint(20); public string toString(){return id + ":" + "i4:" + i4 + "、i5 =" + i5; } public static void main(string [] args){finalData fd1 = new finalData( "fd1"); System.out.println(fd1); System.out.println( "新しいfinalDataの作成"); finalData fd2 = new finalData( "fd2"); System.out.println(fd1); System.out.println(fd2); }}
結果
FD1:I4:6、I5 = 3 Creating New FinalDataFD1:I4:6、I5 = 3FD2:I4:17、I5 = 3
例セクションでは、最終値を静的(I5)と非静的(I4)として定義することの違いを示しています。この違いは、コンパイラがコンパイルされた値を均等に扱うため、ランタイム中に値が初期化された場合にのみ表示されます。 (そして、彼らは最適化から姿を消すかもしれません。)プログラムを実行すると、この違いがわかります。 FD1およびFD2では、2番目のFinalDataオブジェクトを作成してもi5の値を変更できないことに注意してください。これは、新しいオブジェクトが作成されるたびにではなく、ロード時に初期化される静的であるためです。
例4
クラス値{int i; public Value(int i){this.i = i; }} public class…{private value v1 = new Value(11);プライベート最終価値v2 = new値(22);プライベート静的最終値v3 = new値(33); …} public static void main(string [] args){…fd1.v2.i ++; // ok- objectは一定ではありません! fd1.v1 = new value(9); // ok- final fd1.v2 = new value(0); //エラー:参照を変更できないfd1.v3 = new値(1); //エラー:参照を変更できない…} V1からV3への変数は、最終参照の意味を示しています。 main()でわかるように、V2が最終的なものであるという理由だけでその価値を変更できないとは思わない。それは参照であるため、最終的なことは、V2を別の新しいオブジェクトに再び指すことができないことを意味します。
例5
パブリッククラス…{private final int [] a = {1,2,3,4,5,6}; …} public static void main(string [] args){…for(int i = 0; i <fd1.a.length; i ++)fd1.a [i] ++; // ok- objectは一定ではありません。 fd1.a = new int [3]; //エラー:参照を変更できません…}配列に対して同じ意味を持つこと(値を変更できますが、新しいオブジェクトを指すことはできません)、アレイは別の参照です。
1.4最終配列の制限を解決します
配列参照は最終的に宣言できますが、配列の要素はできません。これは、パブリックファイナルアレイフィールドを公開したり、メソッドを介してそれらのフィールドに参照を返すクラスも可変ではないことを意味します。
//不変 - 状態配列は悪意のあるによって変更される可能性がありますpublic string [] getStates(){return States; }}
同様に、オブジェクト参照は最終フィールドとして宣言することができますが、参照するオブジェクトは依然として可変性があります。最終フィールドを使用して不変オブジェクトを作成する場合は、アレイまたは可変オブジェクトへの参照がクラスを「エスケープ」することを防ぐ必要があります。アレイを繰り返しクローン化することなくこれを行うには、簡単な方法は配列をリストに変換することです。
// Immutable -PublicClass Safestates {private final String [] States = new String [] {"Alabama"、 "Alaska"、 "ect"};プライベート最終リストSTATESASLIST = new AbstractList(){public Object get(int n){return States [n]; } public int size(){return states.length; }}; public List getStates(){return StatesAslist; }}
1.5最終パラメーターの使用について
別の使用法は、メソッドのパラメーターを最終として定義することです。基本タイプの変数の場合、これには実用的な意味がありません。これは、基本型の変数がメソッドを呼び出すときに値を渡す、つまり、通話ステートメントに影響を与えることなくメソッドのパラメーター変数を変更できるためです。ただし、オブジェクト変数の場合、オブジェクト変数が通過時に参照に渡されるため、非常に実用的です。このようにして、メソッド内のオブジェクト変数の変更は、呼び出しステートメントのオブジェクト変数にも影響します。オブジェクト変数をメソッドのパラメーターとして変更する必要がない場合、宣言にfinalを明示的に使用すると、意図せずに呼び出しメソッドが変更され、影響を与えることができなくなります。
1.6内部クラスのパラメーター変数について
さらに、内部クラスのメソッドでパラメーター変数を使用する場合、このパラメーター変数を使用する前に最終的に宣言する必要があります。
例6 incrass.java
public class inclass {void innerclass(final string str){class iclass {iclass(){system.out.println(str); }} iclass ic = new iClass(); } public static void main(string [] args){intrass inc = new incrass(); Inc.InnerClass( "Hello"); }} 2。最終的な方法
2.1最終的な方法の使用
1)特定の関数の動作が継承プロセス中に変更されず、オーバーライドできないことを確認するために、最終的な方法を使用できます。
2)クラス内のすべてのプライベートおよび静的な方法は、当然最終的なものです。
2.2最終キーワードとプライベートキーワード
クラス内のすべてのプライベート方法は、暗黙的に最終的に指定されています。プライベート方法は使用できないため、上書きすることはできません。
「オーバーライド」は、メソッドがベースクラスのインターフェイスの一部である場合にのみ表示されます。つまり、オブジェクトをプリミティブタイプに上向きに変換し、同じ方法を呼び出すことができなければなりません。メソッドがプライベートである場合、基本クラスのインターフェイスの一部ではありません。クラスに隠されたコードだけですが、同じ名前です。ただし、エクスポートクラスで同じ方法でパブリック、保護、またはパッケージアクセス方法が生成された場合、メソッドはベースクラスで発生する「同じ名前のみ」ケースを生成しません。この時点で、メソッドをオーバーライドせず、新しいメソッドを生成しました。プライベート方法は触れられず、効果的に隠すことができるため、属するクラスの組織構造の存在を除いて、他に考慮する必要はありません。
3。最終クラス
クラスが最終として定義されている場合、クラスを継承することはできません。また、最終クラスが継承を禁止するため、最終クラスのすべての方法は、上書きできないため、最終として暗黙的に指定されます。
ファイナルは、メソッド間のリンクが壊れないようにするために、クラスまたは方法で使用されます。たとえば、クラスXの方法の実装が、方法Mが何らかの形で機能すると仮定しているとします。 XまたはMを最終的に宣言すると、導出されたクラスがこのようにMを再定義することができなくなり、Xが異常に動作します。これらの内部相関なしにXを実装する方が良いかもしれませんが、これは常に可能であるとは限りません。ファイナルを使用すると、将来の互換性のない変更を防ぐことができます。
PS:ファイナル、最終的、最終決定の違い