戻る

クラスに対するアクセス制御

   メンバーに対するアクセス制御については、既に説明した。
  アクセス修飾子は、メンバーだけでなく、クラスを修飾する事もできる。

   public class A { ・・・・・このクラス宣言にはpublicがついている
     …
     …
   }

   class B ・・・・・・・・・・・このクラス宣言にはpublicがついていない
     …
     …
   }

   本節では、クラス宣言につけるアクセス修飾子の効果についてまとめる。

クラス宣言におけるアクセス修飾子

   アクセス修飾子は、クラス宣言やメンバー(フィールドやメソッド)の定義で使われる。

   public class A { ・・・・・・・・クラス
    private int value; ・・・・・フィールド(メンバー)

    public void run( ) { ・・・・メソッド(メンバー)
      …
    }
   }

   クラス宣言で使えるアクセス修飾子は、publicだけである。したがってpublicがつくか付かないかにより、そのクラスが使える範囲が来まる。

 アクセス修飾子  アクセス制御
 なし  そのクラスは同じパッケージからのみアクセス可能 
 public  そのクラスはどのクラスからもアクセス可能

   publicで修飾されたクラスをpublicクラスという。publicクラスはどのクラスからも使う事が出来る。

   public class A { ・・・・・publicクラス
     …
     …
   }

   アクセス修飾子がつかないクラスは、同じパッケージにあるクラスからのみ使う事が出来る。
  他のパッケージにあるクラスからは、使う事が出来ない。

   class B { ・・・・・このクラスは同じパッケージにあるクラスからのみ使う事が出来る。
     …
     …
   }

ソースファイルとアクセス修飾子

   ソースファイルの名前と、クラスを修飾するアクセス修飾子とは大いに関係がある。

 クラスの種類  宣言の位置
 非publicクラス   どのソースファイルでも可能
 publicクラス  クラス名と同じソースファイルでのみ宣言可能 

   publicクラスは同名のソースファイルで宣言しなければならない。したがって、1つのソースファイルに宣言できるpublicクラスは1つだけである。
  しかし、非publicクラスなら、1つのソースファイルにいくつも宣言する事ができる。

  (ソースファイル A.java)
   public class A { ・・・・・publicクラス・ソースファイルと同じ名前なので○
     …
   }
   public class B { ・・・・・publicクラス・ソースファイルと異なる名前なので×
     …
   }
   class C { ・・・・・・・・・・非publicクラスなので○
     …
   }

   なお、1つのソースファイルに複数のクラスを宣言した場合、コンパイルするとクラスごとに別のクラスファイルが出来上がる。

   先に作成したパッケージPackを例にソースファイルとアクセス修飾子の関係を実際に見てみる。
  現在、このパッケージには、Pack_1というクラスが1つだけ含まれている。

   $ dir Pack/*class ・・・・・パッケージPackにあるクラスを調べる
   Pack/Pack_1.class ・・・・Pack_1というクラスがある
   $ _

   このパッケージPackに次のパッケージを追加する。

   サンプル:Pack_2.java

   //
   //Pack_2.java---アクセス修飾子のないクラスを使う
   //
   package Pack;

   public class Pack_2 { ・・・・・publicクラス(ソースファイル名と同じ)
    public void show( ) {
     System.out.println("Pack_2: show");
    }

   public void use_pack_3( ) {
     Pack_3 p = new Pack_3( ); ・・・・・ここでクラスPack_3を使う
     p.show( );
    }
   }

   class Pack_3 { ・・・・・非publicクラス
    public void show( ) {
     System.out.println("Pack_3: show");
    }
   }

   このPack_2.javaには、2つのクラスが含まれている。Pack_2とPack_3である。
  したがってPack_2.javaをコンパイルすると、2つのクラスファイルPack_2.class、Pack_3.classが出来上がる。

   $ javac Pack_2.java ・・・・・・・・・Pack_2.javaをコンパイル
   $ dir *class
   Pack_2.class Pack_3.class ・・・作成されたクラスファイル
   $ _

   これらのクラスファイルはパッケージPackに所属する。
  なぜならソースファイルの先頭にあるpackage文で所属するパッケージを指定しているからである。

   package Pack;

   そこで、これらのクラスファイルをディレクトリPackにファイルする。
  なお、既にパッケージファイルPackにはPack_1というクラスがあるので、これで、ディレクトリPackには合計3個のクラスファイルが存在している。

   $ dir Pack/*class ・・・・・ディレクトリPackにあるクラスファイルをリストする
   Pack/Pack_1.class Pack/Pack_2.class Pack/Pack_3.class
   $ _

   次にパッケージPackに含まれる3つのクラスを使うサンプルアプリケーションを示す。

   サンプル;Access.java

   //
   //Access.java---アクセス修飾子のテスト
   //
   import Pack.*; ・・・・・パッケージPackを使うためのimport文

   public class Access {
    public static void main(String[ ] args) {
     Pack_1 p1 = new Pack_1( ); ・・・・・クラスPack_1を使う
     p1.show( )

     Pack_2 p2 = new Pack_2( ); ・・・・・クラスPack_2を使う
     p2.show( );
     p2.use_Pack_3( );

     Pack_3 p3 = new Pack_3( ); ・・・・・クラスPack_3を使う
     p3.show8 );
    }
   }

   ところが、このアプリケーションをコンパイルしようとすると、次のようにエラーになってしまう。

   $ javac Access.java
   Access.java:15: Pack の Pack.Pace_3 は public ではありません。パッケージ外からはアクセスできません。
     Pack_3 p3 = new Pack3( );  //クラスPack_3を使う
     ^
   Access.java:15: Pack の Pack.Pack_3 は public ではありません。パッケージ外からはアクセスできません。
     Pack_3 p3 = new Pack3( );  //クラスPack_3を使う
                ^
   Access.java:15: Pack.Pack_3 の Pack_3( ) は publicではありません。パッケージ外からのアクセスはできません。
     Pack_3 p3 = new Pack_3( );  //クラスPack_3を使う
             ^
   Access.java:16: Pack.Pack_3 の show( ) はpublic クラスまたはインターフェースではありません。パッケージ外からはアクセスできません。
     p3.show( );
      ^
   エラー4個

   このエラーは当然である。パッケージPackに含まれる3つのクラスのアクセス修飾子を調べればすぐに分かる。
   これらのクラスのうちPack_1とPack_2はpublicクラスなので、どのクラスからも使う事が出来る。
  もちろんmainメソッドが含まれるクラスAccessからも使用可能である。
  しかし、Pack_3は非publicクラスなので同じパッケージPackにあるクラスからしか使う事が出来ない。これがコンパイルエラーになった原因である。
   コンパイルエラーが出ないようにするには、Pack_3を使う部分をコメントにしてしまえば良い。

   public class Access {
    public static void main(String[ ] args9 {
      …
      …
    //Pack_3 p3 = new Pack_3( ); ・・・コメントにする
    //p3.show( );
    }
   }

   なお、前項のPack_2.javaでクラスPack_2の中からPack_3を使っているが、これはコンパイルエラーにはならない。
  なぜならPack_2はPack_3と同じパッケージPackに含まれるからである。

   package Pack; ・・・以下のクラスはパッケージPackに所属する

   public class Pack_2 {
     …
     …

    public void use_Pack_3( ) {
     Pack_3 p = new Pack_3( ); ・・・・ここでPack_3を使っている
     p.show
    }
   }

メンバーに対するアクセス制御(2)

   メンバーに対するアクセス制御については、すでに説明した。そこでは、次の2つのアクセス修飾子を紹介した。

   private ― この修飾子で修飾されたメンバーは他のクラスから参照する事ができない。(そのメンバーを外部に非公開にする。)
   public  ― この修飾子で修飾されたメンバーは他のクラスから参照する事が出来る。(そのメンバーを外部に光景にする。)

   パッケージを使えるようになった今、これに第3のアクセス修飾子を追加する。

   なし  ― アクセス修飾子で修飾されていないメンバーは同じパッケージにあるクラスからのみ参照できる。

   つまり、privateやぷbぃcといったアクセス修飾子をつかないと、そのメンバーのアクセス制御はどうなるかという問題である。
  この場合、そのメンバーはprivateやpublicとは異なるスコープを持つ。
  すなわち、同じパッケージに所属するクラスからは参照できるが、他のパッケージにあるクラスからは、参照できない。
   例えば、次のクラスNonAccessを例に説明する。

   package Pack; ・・・・・所属パッケージはPack

   public class NonAccess {
    int num; ・・・・・アクセス修飾子のないフィールド

    void show( ) { ・・・・・アクセス修飾子のないメソッド
     System.out.println("num = " + num);
    }
   }

   NonAccessは、パッケージPackに所属するクラスである。このクラスは、1つのフィールドと1つのメソッドを持つ。
  これらのメンバーはいずれもアクセス修飾子で修飾されていない。
   さて、このクラスを次のようにして利用したとする。

   NonAccess n = new NonAccess( ); ・・・・・インスタンスを生成

   n.num = 987654321; ・・・・・フィールドを参照
   n.show( ); ・・・・・・・・・・・・・・メソッドを参照

   もし、このコードを同じパッケージに所属するクラスの中に置くのなら問題は無い。
  しかし、他のパッケージにあるクラスの中に置いたなら、そのコードはコンパイルエラーになる。
  なぜなら、アクセス修飾子で修飾されていないメンバーは、同じパッケージにあるクラスからのみ参照出来るからである。
   以上をテストするための、サンプルパッケージとサンプルアプリケーションを次に示す。

   サンプル:NonAccess.java

   //
   //NonAccess.java---アクセス修飾子のないメンバー
   //
   package Pack;

   public class NonAccess {
    int num;   //アクセス修飾子のないフィールド

    void show( ) {   //アクセス修飾子のないメソッド
     System.out.println("num = " + num);
    }
   }

   //同じパッケージからアクセス修飾子のないメンバーを使う
   class Member {
    public void run( ) {
     NonAccess n = new NonAccess( );
     n.show( );
    }
   }

   このサンプルパッケージでは、クラスMemberの中からクラスNonAccessのメンバーを参照している。
  これは、同じパッケージからの参照なので問題ない。次にNonAccess.javaをコンパイルした所を示す。

   $ javac NonAccess.java
   $ _ ・・・・・コンパイルエラーになっていない

   次のサンプルアプリケーションは、別のパッケージからNonAccessのメンバーを参照する例である。

   サンプル:Access_2.java

   //
   //Access_2.java---アクセス修飾子のテスト(その2)
   //
   import Pack.*;

   public class Access_2 {
    public static void main(String[ ] args) {
     NonAccess n = new NonAccess( );
     n.num = 987654321;
     n.show( );
    }
   }

   このアプリケーションに含まれるクラスAccess_2は、package文の指定が無いのでパッケージPackには所属しない。
  このため、クラスAccess_2からNonAccessのメンバーを参照する事は出来ない。
  したがって、このアプリケーションをコンパイルすると、次のようにコンパイルエラーになってしまう。

   $ javac Access_2.java
   Access_2.java:9: Pack.NonAccess の num は public ではありません。パッケージ外からはアクセスできません。
     n.num = 987654321;
      ^
   Access_2.java:10: Pack.NonAccess の show( ) は publicではありません。パッケージの外からはアクセスできません。
     n.show( );
      ^
   エラー2個

次へ