アクセス修飾子はその名前の通り、クラス等にアクセス制限を付加する機能です。
アクセス修飾子の概要
アクセス修飾子には4つの種類があります。
- public
- protected
- 修飾子なし
- private
となっており、それぞれでアクセスできる範囲が変わります。アクセス(もしくは参照)できる範囲をスコープと呼びます。アクセスできる範囲が広いと便利ですがセキュリティが低くなり、アクセスできる範囲が狭いと不便になりますがセキュリティは高くなります。
ここでのセキュリティの一例をあげると、クラスの部品であるフィールド(状態)の値が正常であることや、メソッド(操作)が適切な範囲内で行えるようになっていることを指します。
要約するとアクセス修飾子を用いることで、クラスのフィールドやメソッド、もしくはクラスそのものを保護させることができます。
アクセス修飾子の種類と範囲
アクセス修飾子はその種類に応じてアクセスできる範囲が異なります。ポイントはアクセス修飾子を記述しないこともアクセス修飾子の種類の一つです。
アクセス範囲をまとめた表は以下の通りです。
種類 | 別パッケージ | 同じパッケージ | 同じクラス |
---|---|---|---|
public | 〇 | 〇 | 〇 |
protected | △ | 〇 | 〇 |
記述なし | × | 〇 | 〇 |
private | × | × | 〇 |
publicがどこからでもアクセスできるようになっており、privateは同一クラス内でしかアクセスできなようになります。
protectedの「別パッケージ」が△になっていますが、継承関係がある場合にのみ別パッケージからアクセスできるようになります。
上の表と説明をまとめると以下のようになります。
種類 | アクセス範囲 |
---|---|
public | 別パッケージからのアクセスが可能 |
protected | 別パッケージからのアクセスは継承関係があれば可能 |
記述なし | 同一パッケージからのアクセスのみ可能 |
private | クラス内のみ利用可能 |
図解にすると以下のようになります。図解の例ではメソッドにアクセス修飾子を付与しています。
メソッドにアクセス修飾子publicを付与した場合
メソッドにアクセス修飾子protectedを付与した場合
メソッドにアクセス修飾子を付与しなかった場合
メソッドにアクセス修飾子privateを付与した場合
アクセス修飾子の種類と記述箇所
アクセス修飾子はクラス及びそのメンバ(部品)に記述することができます。アクセス修飾子を記載できる代表的なものには「クラス」「フィールド」「メソッド」「コンストラクタ」があります。
アクセス修飾子 (クラス) |
アクセス修飾子 class クラス名{ |
---|---|
記述例 | public class Test{ |
アクセス修飾子 (フィールド) |
アクセス修飾子 型 フィールド名 ; |
---|---|
記述例 | private int number ; |
アクセス修飾子 (メソッド) |
アクセス修飾子 戻り値の型 メソッド名(引数){ |
---|---|
記述例 | public void output(){ |
アクセス修飾子 (コンストラクタ) |
アクセス修飾子 クラス名(引数){ |
---|---|
記述例 | public Test(){ |
しかし、フィールドやメソッドおよびコンストラクタには4種類全てを付与することができますが、クラスにはpublicと修飾子なししか指定できません。
ローカル変数はフィールドと同じ変数ではありますが、そもそもメソッド内部でのみの参照になる為、アクセス修飾子を付与できません。
※見方を変えると「修飾子なし=メソッド内のみのアクセス範囲」と捉えることもできます
アクセス修飾子 サンプルプログラム
以下のプログラムをgameフォルダに「AccessTest.java」、workフォルダには「Number39.java」という名前で保存します。(以下、階層構造図)
保存が完了したら、コマンドプロンプトを起動し、Number38.javaをコンパイルしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package game; public class AccessTest{ public void a(){ System.out.println("public"); } protected void b(){ System.out.println("protected"); } void c(){ System.out.println("修飾子なし"); } private void d(){ System.out.println("private"); } } |
1 2 3 4 5 6 7 8 9 10 11 |
import game.AccessTest; class Number39{ public static void main(String[] args){ AccessTest at = new AccessTest(); at.a(); at.b(); at.c(); at.d(); } } |
実行例
C:\work>javac Number39.java
Number39.java:7: エラー: b()はAccessTestでprotectedアクセスされます
at.b();
^
Number39.java:8: エラー: AccessTestのc()はpublicではありません。パッケージ外からはアクセスできません
at.c();
^
Number39.java:9: エラー: d()はAccessTestでprivateアクセスされます
at.d();
^
エラー3個
※実行例はコンパイル例を表示しています。
サンプルプログラムの解説
今回のサンプルプログラムはコンパイルエラーとなります。
今回はAccessTest.javaのクラス及びメソッドに様々なアクセス修飾子を付与しています。
アクセス修飾子 | クラス名 | |||
---|---|---|---|---|
public | AccessTest | |||
アクセス修飾子 | メソッド名 | 戻り値の型 | 引数 | 処理内容 |
public | a | void | なし | 表示 |
protected | b | void | なし | 表示 |
修飾子なし | c | void | なし | 表示 |
private | d | void | なし | 表示 |
そのAccessTestクラスを別パッケージから利用するNumber39.javaがあり、インスタンス生成およびメソッドの呼び出しをおこなっています。
別パッケージからのアクセスとなりますので、public以外が付与されているクラスとメソッドはコンパイルエラーとなり利用できません。
以下はNumber39.javaを修正したプログラムです。(AccessTest.javaは修正なし)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import game.AccessTest; //AccessTestを継承 class Number39 extends AccessTest{ public static void main(String[] args){ AccessTest at = new AccessTest(); at.a(); //at.b(); //at.c(); //at.d(); } //AccessTestのb()メソッドを利用するメソッドの作成 void exe(){ b(); } } |
修正は以下のようにしています。
- AccessTestを継承(3行目)
- b()メソッドの呼び出しをコメント(7行目)
- c()メソッドの呼び出しをコメント(8行目)
- d()メソッドの呼び出しをコメント(9行目)
- b()メソッドを呼び出すメソッドの作成(12-14行目)
別パッケージからでも、サブクラス側からであればprotected修飾子が付与されているb()メソッドはアクセス可能ということを確認しています。
main()メソッド内部ではb()メソッドは呼び出しできない(理由はstaticのページで紹介)ため、exe()メソッド内部から呼び出しています。
インポート 復習問題
- アクセス修飾子の説明として正しいものを選んでください。
- 解答群
- アクセス修飾子はクラスに指定できない
- publicはクラスに指定できる
- protectedはクラスに指定できる
- privateはクラスに指定できる
- アクセス修飾子の説明として正しいものを選んでください。
- 解答群
- アクセス修飾子はローカル変数にも付与できる
- アクセス修飾子はコンストラクタには指定できない
- アクセス修飾子はpublicが一番アクセス範囲が広い
- アクセス修飾子はprivateが一番アクセス範囲が広い
- お疲れ様でした。
まとめ
- アクセス修飾子を付与しクラス及びメンバのアクセス範囲を設定できる
- public、protected、修飾子なし、privateの4種類
- アクセス範囲外の利用はコンパイルエラーとなる