戻る
クラスに対するアクセス制御
メンバーに対するアクセス制御については、既に説明した。
アクセス修飾子は、メンバーだけでなく、クラスを修飾する事もできる。
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個
次へ