保護されています
保護されたアクセス権の問題について話しましょう。以下の例を参照してください:
test.java
class myobject {} public class test {public static void main(string [] args){myobject obj = new Myobject(); obj.clone(); //エラーをコンパイルします。 }}タイプオブジェクトからのメソッドクローンは表示されません。
object.clone()が保護された方法であることをすでに理解しています。これは、この方法に同じパッケージ(java.lang)とit(java.lang.object)のサブクラスによってアクセスできることを示しています。これがMyobjectクラス(java.lang.objectのデフォルト継承)です。
同様に、テストはjava.lang.objectのサブクラスでもあります。ただし、2つのサブクラスは同じ親クラスから継承されますが、別のサブクラスの保護された方法に1つのサブクラスにアクセスすることはできません。
例2をもう一度見てみましょう:
test2.java
class myobject2 {protected object clone()は、clonenotsupportedexceptionをスローします{return super.clone(); }} public class test2 {public static void main(string [] args)throws clonenotsuptedexception {myobject2 obj = new Myobject2(); obj.clone(); // OKをコンパイルします。 }}ここでは、Myobject2クラスの親クラスのclone()メソッドをオーバーライドし、別のクラスTest2のclone()メソッドを呼び出し、コンパイルして渡します。
編集の理由は明らかです。 Myobject2クラスのclone()メソッドをオーバーライドすると、myobject2クラスとtest2クラスは同じパッケージの下にあるため、この保護されたメソッドはtest2クラスに表示されます。
この時点で、Javaの浅いコピー記事の第2.2章の声明を思い出します。この文の理由を理解しました(他のクラスがこのクラスのclone()メソッドを呼び出すために、過負荷後、clone()メソッドの属性を公開する必要があります)。
例3を見てみましょう。
test3.java
パッケージ1class myobject3 {protected object clone()throws clonenotsupportedexception {return super.clone(); }} package 2public class test3 extends myobject3 {public static void main(string args []){myobject3 obj = new Myobject3(); obj.clone(); //エラーをコンパイルします。 test3 tobj = new test3(); tobj.clone(); // comprie ok。 }}ここでは、test3クラスを使用してmyobject3を継承します。これらの2つのクラスには異なるパッケージがあることに注意してください。そうでなければ、例2の場合です。TEST3クラスでは、test3クラスのインスタンスtobjのclone()メソッドを呼び出し、コンパイルして通過します。また、Myobject3クラスのInstance OBJのclone()メソッドを呼び出すことも呼び出され、コンパイルエラーが呼び出されます!
予期しない結果、保護された方法に継承されたクラスでアクセスできませんか?
クラスTest3がクラスMyobject3(そのクローン法を含む)を継承することは明らかである必要があります。したがって、クラスTest3で独自のクローンメソッドを呼び出すことができます。ただし、クラスMyobject3の保護された方法は、異なるBUNサブクラステスト3には見えません。
これが「一言で言えば、ジャバ」からの別の一節です。
保護されたアクセスには、もう少し研究所が必要です。クラスAが保護されたフィールドXを宣言し、異なるパッケージで定義されているクラスBによって拡張されるとします(この最後のポイントが重要です)。クラスBは保護されたフィールドXを継承し、そのコードは、Bの現在のインスタンスまたはコードが参照できるBの他のインスタンスでそのフィールドにアクセスできます。ただし、これは、クラスBのコードがAの任意のインスタンスの保護されたフィールドの読み取りを開始できるという意味ではありません。オブジェクトがAのインスタンスであるがBのインスタンスではない場合、そのフィールドは明らかにBで継承されず、クラスBのコードはそれらを読み取ることができません。
ちなみに、中国の多くのJavaの本は、アクセス許可(さまざまな形式と一貫したコンテンツ)を導入する際に、一般にこのように説明されています。
メソッドのアクセス制御:
静的
1。キーワード静的(最初にこれらを覚えておいて、次に読み取ります)
1)静的メソッドと静的変数は、特定のクラスに属するがクラスではないオブジェクトです。
2)静的メソッドと静的変数への参照は、クラス名を介して直接参照されます。
3)静的方法では、非静的な方法と非静的なメンバー変数を呼び出すことはできません。そうでなければ、それは大丈夫です。
4)静的変数は、一部のプログラムの他の言語のグローバル変数に類似しており、プライベートでない場合はクラスの外でアクセスできます。
2。静的を使用するとき
クラス(オブジェクト)のインスタンスを作成すると、通常、新しいメソッドを使用して、このクラスのデータスペースが作成され、そのメソッドが呼び出されます。
ただし、nオブジェクトでクラスを作成できることを願っていますが(明らかにこれらのnオブジェクトのデータ空間は異なります)、これらのnオブジェクトのデータの一部は同じです。つまり、クラスにあるインスタンスの数に関係なく、データにはこれらのインスタンスのメモリコピーがあります(例1を参照)。これは、静的変数の場合です。
別のシナリオは、クラスを含むクラスのオブジェクトにメソッドを関連付けないようにしたいということです。つまり、オブジェクトが作成されていない場合でも、この方法は呼び出すことができます。静的方法の重要な使用法は、オブジェクトを作成せずに呼び出すことです(例2を参照)。これは、静的な方法の場合です。
また、内部クラスでは特別な使用があります。通常、通常のクラスは静的と宣言されることは許可されておらず、内側のクラスのみがそれを行うことができます。現時点では、静的と宣言されたこの内部クラスは、外側のクラスをインスタンスする必要なく、通常のクラスとして直接使用できます(例3を参照)。これは、静的クラスの場合です。
例1
public class tstatic {static int i; public tstatic(){i = 4; } public tstatic(int j){i = j; } public static void main(string args []){system.out.println(tstatic.i); tstatic t = new tstatic(5); //オブジェクト参照を宣言し、インスタンス化します。この時点でi = 5 System.out.println(ti); tstatic tt = new tstatic(); //オブジェクト参照を宣言し、インスタンス化します。この時点で、i = 4 System.out.println(ti); System.out.println(tt.i); System.out.println(ti); }}
結果:
05444
静的変数は、クラスがロードされるときに作成されます。クラスが存在する限り、静的変数が存在します。定義されたときに初期化する必要があります。上記の例では、Iが初期化されていないため、デフォルトの初期値0が取得されます。静的変数は1回のみ初期化でき、静的変数は最後の初期化のみを受け入れます。
実際、これは依然として、静的変数を共有する複数のインスタンスの問題です。
例2
静的と宣言されていません
クラスクラス{int b; public void ex1(){} class classb {void ex2(){int i; classa a = new classa(); i = ab; //ここで、メンバー変数B a.ex1()へのアクセスオブジェクト参照。 //ここで、メンバー関数へのアクセスはオブジェクト参照}}}}}}
静的と宣言されています
クラスクラス{static int b; static void ex1(){}} class classb {void ex2(){int i; i = classa.b; //ここで、メンバー変数B classa.ex1()にアクセスしてクラス名を介して。 //ここでメンバー関数へのアクセスクラス名を介してEX1}}静的方法を使用する場合、非静的な方法では静的な方法で呼び出され、非静的なメンバー変数を参照することはできないことに注意してください(これまたはスーパーは、静的方法ではいかなる方法でも参照できません)。その理由は非常に簡単です。静的なものの場合、JVMがクラスをロードすると、これらの静的スペースがメモリ内に開き(クラス名を介して直接参照できます)、現時点では、非静的な方法とメンバー変数が配置されているクラスはインスタンス化されていません。
したがって、非静的な方法とメンバー変数を使用する場合は、メソッドまたはメンバー変数が静的メソッドにあるクラスを直接インスタンス化できます。それが、public static void mainがそれを行う方法です。
例3
public class staticcls {public static void main(string [] args){outercls.innercls oi = new outercls.innercls(); //この前に新しいoutourclsをする必要はありません}} class outercls {public static class inentercls {innerycls(){system.out.out.outln(innercls "); }}}
結果:
innercls
3。静的初期化
静的によって定義された変数は、それらが表示される順序に関係なく、他の非静的変数よりも優先されます。静的コードブロック(コードの一部に続いて)を使用して、明示的な静的変数初期化を実行します。このコードは、クラスが初めて読み込まれたときにのみ初期化されます。以下の例を参照してください。
クラス値{static int c = 0; value(){c = 15; } value(int i){c = i; } static void inc(){c ++; }} class count {public static void prt(string s){system.out.println(s); }値v = new値(10);静的値V1、V2; static {prt( "calsカウントv1.c =" + v1.c + "v2.c =" + v2.c); v1 = new値(27); prt( "cals count count v1.c =" + v1.c + "v2.c =" + v2.c); v2 = new value(); prt( "cals count count v1.c =" + v1.c + "v2.c =" + v2.c); }} public class tstaticBlock {public static void main(string [] args){count ct = new count(); count.prt( "in the main:"); count.prt( "ct.c =" + ct.vc); count.prt( "v1.c =" + count.v1.c + "v2.c =" + count.v2.c); count.v1.inc(); count.prt( "v1.c =" + count.v1.c + "v2.c =" + count.v2.c); count.prt( "ct.c =" + ct.vc); }}
結果:
calssカウントv1.c = 0 v2.c = 0の静的ブロックでは、calssカウントv1.c = 27 v2.c = 27の静的ブロックcalssカウントv1.c = 15 v2.c = 15でメイン:Ct.c = 10v1.c = 10 v2.c = 10v1.c = 11 v2.c = 11ct.c = 11
V、V1、またはV2であろうと、動作するメンバー変数は同じ静的変数cです。
クラスカウント、V1およびV2(静的値V1、V2;)で、静的コードブロック(静的{})を初期化し、最後にvを初期化します。