ホームページ  >  記事  >  Java  >  Java アクセス許可制御 - protected キーワードについて詳しく学習します (図)

Java アクセス許可制御 - protected キーワードについて詳しく学習します (図)

黄舟
黄舟オリジナル
2017-03-14 12:01:272301ブラウズ


概要:

クラス内で、そのメンバー (メンバー変数メンバーメソッドを含む) にアクセスできるかどうかは、メンバーの修飾子とクラスかどうかによって決まります。他のクラスからアクセスできるかどうかは、クラスの修飾子に応じて異なります。 Java には、クラス メンバーのアクセス許可修飾子には、private、none (デフォルトではパッケージ アクセス許可)、protected、public の 4 種類があります。このうち、クラス (内部クラスを除く) を変更できるのは、パッケージ アクセス許可と public だけです。特に Java の入門書では、protected を一般的な形で紹介していることが多く、誤解を招くことが多いです。したがって、この記事では、protected キーワードの意味合いと使用法を明らかにすることに重点を置き、その他の修飾子をいくつか紹介します。


著作権表示:

この記事の原著者: Rico the nerd
著者ブログアドレス: http://www.php.cn/


1. パッケージ

パッケージの使用については、 1 つの点に注意する必要があります: プロジェクト内で 2 つの同一のパッケージ名を使用することはできません。つまり、パッケージ名をプロジェクト内の他のパッケージ名と重複させることはできません。これには、カスタム パッケージ名だけでなく も含まれます。プロジェクトによる参照 クラス ライブラリ のパッケージ名。 以下の例を見てください:

package java.lang;public class MyObject {
    public static void main(String[] args) throws CloneNotSupportedException {
        Object o = new Object();
        System.out.println(o.hashCode());
    }
}

プログラムに付けたパッケージ名は java.lang です。実際、java.lang は JDK で使用されるパッケージ名であることがわかっています。

プログラムは正常にコンパイルできますが、プログラムを実行すると、図に示すように、パッケージの競合警告が表示され、"java.lang.SecurityException: Prohibited package name: java.lang"例外がスローされます。下に。

Java アクセス許可制御 - protected キーワードについて詳しく学習します (図)

Java アクセス許可制御 - protected キーワードについて詳しく学習します (図)

さらに、次のことに注意する必要があります:

プログラム内で Package ステートメントを使用する場合、それはファイル内のプログラム コードの コメント を除く最初の文である必要があり、それ以外の場合は使用できません。編集済み。


2. Java アクセス権の概要

クラス内で、そのクラスのメンバー (メンバー変数やメンバーメソッドを含む) が他のクラスからアクセスできるかどうかは、メンバーの修飾子によって異なります。 Java には、クラス メンバーのアクセス修飾子として、

private、none (デフォルトではパッケージ アクセス)、protected、public の 4 種類があります。 権限制御は次の表に示すとおりです。

Java アクセス許可制御 - protected キーワードについて詳しく学習します (図)

Javaの

クラス(その内部メンバーではないため、2つは区別する必要があります)であるという事実に特別な注意を払う必要があります。 アクセス許可修飾子 タイプは public と "none" (つまり、パッケージ アクセス権) の 2 つだけですが、private または protected はありません (特殊なケースがあり、内部クラスのみが private または protected にできます。詳細については、内部クラスについては、私のブログ「Java 内部クラスのレビュー」を参照してください)。 したがって、非内部クラスの場合は、パッケージ アクセスまたは public のみを与えることができます。 他の人にクラスにアクセスさせたくない場合は、すべてのコンストラクターをプライベートとして指定して、誰もがクラスの オブジェクトを作成できないようにすることができます。現時点では、このクラスのオブジェクトはその静的メンバー内でのみ作成できます。この状況は、次の例のような 単一ケース パターン に少し似ています。 、保護されていることを除いて、それらはすべて理解しやすくマスターしやすいものです。ここで簡単に説明します。

  • private:被public修饰的类成员只能在定义它的类中被访问,其他类都访问不到。特别地,我们一般建议将成员变量设为private的,并为外界提供 getter/setter 去对成员变量进行访问,这种做法充分体现了Java面向对象的四大特性(封装,多态,继承,抽象)中的封装思想;

  • 包访问权限:包访问权限就是Java中的默认的权限,具有包访问权限的类成员只能被同一包中的类访问。

      由于 protected 关键字的真正内涵不太容易理解,我们将在下一节专门介绍 protected 关键字。


  • 三. protected 关键字的真正内涵

      很多的有关介绍Java语言的书籍 (包括《Java编程思想》),都对protected介绍的比较的简单,基本都是一句话,就是:被protected修饰的成员对于本包和其子类可见。这种说法有点太过含糊,常常会对大家造成误解。对于protected的成员,要分子类和超类是否在同一个包中两种情况看待,现以 protected方法的调用为例进行说明,protected的成员变量类似。

      实质上,protected方法的调用是否合法(编译是否通过)关键是要看被调用的protected方法从根源上看所在的类对应的包与调用代码所在的类对应的包是否相同,若相同,则合法;否则,不合法。当然,无论如何,子类是可以访问继承而来的属于它自己的受保护方法的。

      我们可以看下面例子进行了解。


    1). 第一种情形:子类与基类不在同一个包中

    //示例一package p1;public class Father1 {
        protected void f() {}   
        // 父类Father1中的protected方法}package p1;
        public class Son1 extends Father {}package p11;
        public class Son11 extends Father{}package p1;
        public class Test1 {
        public static void main(String[] args) {
            Son1 son1 = new Son1();
            son1.f(); // Compile OK,protected方法f()来自于Father1类,与 Test1类 在同一包p1中
            son1.clone(); // Compile Error,protected方法clone()来自于Object类,与 Test1类不在同一包中
    
            Son11 son = new Son11();
            son11.f(); // Compile OK,虽然Son11类在包p11中,但protected方法f()来自于Father1类,与 Test1类在同一包p1中
            son11.clone(); // Compile Error,protected方法clone()来自于Object类,与 Test1类不在同一包中
        }
    }

      在上面的示例中,类Father1、Son1 和 Test1 在同一个包p1下,类Son11在包p11下。但是我们知道,无论Son1类还是Son11类,它们的protected方法f()在根源上都来自于p1包中的类Father1,而由于Test1也在p1包中,因此f()方法对Test1类可见,编译通过。但由于Son1类和Son11类中的clone()方法在根源上均来自于java.lang包下的类Object,与 Test1类不在同一包中,因此clone()方法对Test1类不可见,编译不通过。


    //示例二package p2;
    class MyObject2 {protected Object clone() throws CloneNotSupportedException {       
    return super.clone();
        }
    }package p22;public class Test2 extends MyObject2 {
        public static void main(String args[]) {
           MyObject2 obj = new MyObject2();
           obj.clone(); // Compile Error,protected方法clone()来自于MyObject2类,与 Test2类 不在同一包p1中
    
           Test2 tobj = new Test2();
           tobj.clone();// Complie OK,虽然 protected方法clone()来自于MyObject2类,与 Test2类 不在同一包p1中,但Test2类作为MyObject2类的子类,是可以访问继承而来的属于它自己的受保护方法的。
        }
    }

      在上面的示例中,类MyObject2 和 类Test2 分别在包 p2 和 p22 下。因此,在类Test2中通过MyObject2的引用调用MyObject2的protected方法clone()时,由于类MyObject2 和 类Test2 不在同一包中而编译不通过。但是我们知道,虽然 类Test2 的protected方法clone()在根源上也来源于 类MyObject2,但是Test2类作为MyObject2类的子类,是可以访问继承而来的属于它自己的受保护方法的。


    //示例三package p3;
    class MyObject3 extends Test3 {
    }package p33;public class Test3 {
      public static void main(String args[]) {
        MyObject3 obj = new MyObject3();
        obj.clone(); // Compile OK,protected方法clone()来自于Test3类,而现在正是在Test3类中访问该方法
      }
    }

      在上面的示例中,类MyObject3 和 类Test3 分别在包 p3 和 p33 下。但是由于 MyObject3类的protected方法clone()在根源上来自于类Test3中,而现在正是在Test3类中访问该方法,因此编译通过,原理与示例一类似。


    //示例四package p4;
    class MyObject4 extends Test4 {  
    protected Object clone() throws CloneNotSupportedException {    
    return super.clone();
      }
    }package p44;public class Test4 {
      public static void main(String args[]) {
        MyObject4 obj = new MyObject4();
        obj.clone(); // Compile Error,protected方法clone()来自于MyObject4类,而Test4类与MyObject4类不在同一个包中
      }
    }

      该示例与示例三很类似,唯一不同的是 类MyObject4 重写了从 类Test4 中继承过来的protected方法clone()。这样,MyObject4 的 protected方法clone()在根源上来自于类本身而非Test4类。而类MyObject4 和 类Test4 又不在同一包下,因此编译不通过。


    2). 第二种情形:子类与基类在同一个包中

    //示例五package p5;
    
    class MyObject5 {    protected Object clone() throws CloneNotSupportedException {       return super.clone();
        }
    }public class Test5 {
        public static void main(String[] args) throws CloneNotSupportedException {
           MyObject5 obj = new MyObject5();
           obj.clone(); // Compile OK,protected方法clone()来自于MyObject5类,而Test5类与MyObject5类又在同一个包中
        }
    }

      该示例与示例四很类似,唯一不同的是 类MyObject5 与 类Test5在同一个包p5中。正因为二者在同一包中,因此编译通过。


    //示例六package p6;
    
    class MyObject6 extends Test6{}public class Test6 {
      public static void main(String[] args) {
        MyObject6 obj = new MyObject6();
        obj.clone();        // Compile OK
      }
    }

      在本示例中,由于类MyObject中的protected方法clone()从根源上来自于Test6类,而现在正是在 Test6 中调用protected方法clone(),因此编译通过。


    //示例七package p7;
    
    class MyObject7 extends Test7 {    public static void main(String[] args) {
            Test7 test = new Test7();
            test.clone(); // Compile Error.
      }
    }public class Test {}

      在本示例中,虽然类MyObject7与Test7类在同一个包p7中,但是由于 类Test7 的protected方法clone()从根源上来自于 java.lang.Object类,而其又与MyObject7不在同一个包中,因此编译不通过。


    四. 其他的修饰符

    static:修饰变量和内部类(不能修饰常规类),其中所修饰变量称为类变量或静态变量。静态变量是和类存在一起的,每个实例共享这个静态变量,在类加载时初始化。

    final: finalとして宣言された変数には、宣言時に初期値が与えられなければなりません(もちろん、空白のfinalの場合を除く)。変更された変数は値を変更できません。クラスを変更する場合、クラスはサブクラスを派生できません。メソッドを変更する場合、メソッドをサブクラスでオーバーライドすることはできません。 Final についてより深く理解したい場合は、私のブログ投稿「Java の継承、ポリモーフィズム、クラスの再利用」を参照してください。

    要約: クラスとメソッドを変更します。クラスを変更する場合、メソッドを変更する場合、クラスは抽象メソッドであるため、オブジェクトを作成することはできません。クラスに抽象メソッドがある限り、クラスは抽象として定義する必要がありますが、抽象クラスは必ずしも抽象メソッドを持つ必要はありません。


    5. 概要

    クラス内で、そのメンバー (メンバー変数やメンバーメソッドを含む) が他のクラスからアクセスできるかどうかは、そのメンバーの修飾子に依存します。クラス修飾子。 Java には、クラス メンバーのアクセス許可修飾子には、private、none (デフォルトではパッケージ アクセス許可)、protected、public の 4 種類があります。このうち、クラス (内部クラスを除く) を変更できるのは、パッケージ アクセス許可と public だけです。特に、この記事では、protected キーワードの意味合いと使用法を明らかにすることに重点を置き、その他の修飾子をいくつか紹介します。


    6. 説明

    この章をレビューする過程で、多くの知識ポイントを取り上げましたが、その一部は他のブログ投稿で具体的に言及したため、これ以上詳しくは説明しませんでした。ここにリンクがあります:

    以上がJava アクセス許可制御 - protected キーワードについて詳しく学習します (図)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。