アクセス指定子
メンバへのアクセスの許可
第6日目では、クラスおよびインスタンスの生成について説明しました。ここでは、さらにその内容を深めていこうとしていくことにします。クラスには、フィールドおよび、メソッドと呼ばれるものがあることはすでに説明しました。
このフィールドおよびメソッドには、アクセス許可を指定することにより、アクセスできる範囲を指定することができます。そのために必要なのが、アクセス指定子です。ここでは、アクセス指定子を利用して、メンバの可視性を指定する方法について説明します。
サンプルプログラム
以下のプログラムを実行してみてください。
SampleClass02.javapackage day7; public class SampleClass02 { // コンストラクタ public SampleClass02(){ System.out.println("コンストラクタ"); } // privateメソッド private void method1(){ System.out.println("method1(private)"); } // publicメソッド① public void method2(){ System.out.println("method2(public)"); } // publicメソッド② public void method3(){ // privateメソッドの呼び出し method1(); System.out.println("method3(public) : num=" + this.num); } // privateフィールド private int num = 1; }
package day7; public class Sample701 { public static void main(String[] args) { SampleClass02 s = new SampleClass02(); // method1()は、privateなので、外部からはアクセスできない。 //s.method1(); // method2呼び出し s.method2(); // method3呼び出し s.method3(); //numは、privateフィールドなので、外部からはアクセスできない。 //s.num = 1; } }
method2(public)
method1(private)
method3(public) : num=1
SampleClass02のメンバの先頭に、public、privateなどといった文字が書かれています。これが、アクセス修飾子(しゅうしょくし)です。
アクセス修飾子の種類
すでに説明したとおり、アクセス修飾子は、フィールドおよびメソッドへのアクセスの制限を指定します。Javaのアクセス修飾子は、以下のようなものがあります。(表7-1)
表7-1.Javaのアクセス指定子アクセス指定子 | 呼び名 | 意味 |
---|---|---|
public | パブリック | どこからでも呼び出せる。 |
(default) | デフォルト | アクセス指定子が省略されている場合。同じパッケージ内からしか呼び出せない。 |
protected | プロテクティッド | 同じパッケージか、そのサブクラスからしか呼び出せない。 |
private | プライベート | 同じクラス内からしか呼び出せない。 |
この第6日目のサンプルでは、アクセス修飾子が省略されています。そのため、デフォルトであり、同一パッケージないからのアクセスが可能です。ここでは、publicおよび、privateが使われています。
サンプルの解説
以上を踏まえて、サンプルの解説をしてききます。SampleClass02において、method2()および、mehtod3()は、publicなので、外部のクラスである、Sample701.javaからアクセス可能なので、10行目および12行目でアクセスしています。
しかし、メソッドmethod1()および、フィールドnumには、privateがついているので、クラスの外からアクセスできません。8行目および14行目のコメントを外すと、以下のようなエラーメッセージが出ます。
privateのメンバに外部からアクセスした場合のエラーメソッド method1() は型 SampleClass02 で不可視です
フィールド SampleClass02.num は不可視です
at day7.Sample701.main(Sample701.java:8)
しかし、SampleClass02.javaの20行目および、21行目では、method1()および、numにアクセスしています。ここでエラーが出ないのは、同一クラス内だからです
クラスの可視性
また、クラスの先頭に、publicがついていますが、このように、クラス全体の可視性を指定することも可能です。ただ、クラスの場合、指定できる可視性は、publicおよび、デフォルトだけです。publicで指定したクラスは、他のパッケージからアクセスすることができ、デフォルトのクラスは、同一パッケージ内からしかアクセス出来ません。
コンストラクタ
クラス名と同一の名前のメソッド
ところで、SampleClass02.javaの6行目に、クラス名と同一のメソッドがあります。これを、コンストラクタと言います。コンストラクタは、戻り値の指定がありません。そして、特徴としては、インスタンス生成時に、一度だけ呼び出されるという特殊なメソッドです。
実は、インスタンス生成時に、newの後にクラス名を指定しているのは、実はこの、コンストラクタを呼び出していたのです。
コンストラクタの呼び出しカプセル化
サンプルプログラム
Java言語でのプログラムの慣例として、通常フィールドは、privateで隠蔽し、外部からアクセスするメソッドを介して値の変更・取得を行います。これを、カプセル化と言います。以下にサンプルを示しますので、まずは実行してみてください。
SampleClass03.javapackage day7; public class SampleClass03 { // int型のフィールド(privateで隠ぺいされている) private int number = 0; // String型のフィールド(privateで隠されている) private String str = ""; // コンストラクタ(引数つき) public SampleClass03(String str){ this.str = str; } // number変数のセッター public void setNumber(int number){ this.number = number; } // number変数のゲッター public int getNumber(){ return this.number; } // str変数のゲッター public String getStr(){ return this.str; } }
package day7; public class Sample702 { public static void main(String[] args) { // 引数つきコンストラクタの呼び出し SampleClass03 s = new SampleClass03("HelloWorld."); // SampleClass03 s = new SampleClass03(); // numberのセッターで、値を設定 s.setNumber(100); // ゲッターで値を呼び出し、内容を表示 System.out.println(s.getNumber()); System.out.println(s.getStr()); } }
HelloWorld.
セッターとゲッター
SampleClass03.javaを見てもわかる通り、フィールドnumberおよびstrは、privateで隠ぺいされており、外部からアクセスすることはできません。privateで隠ぺいされたフィールドに値を書き込むメソッドを、セッター、値を取得するメソッドのことを、ゲッターと呼びます。(表7-2、図7-1参照)
表7-2.参照フィールド名 | セッター | ゲッター |
---|---|---|
number | void setNumber(int number) | int getNumber() |
str | - | String getStr() |
セッターは、setの後に、変数名がきます。この場合、最初の文字が大文字になる(number→Numberのように)になるのが通例です。ゲッターについても同様です。セッターの引数は、また、決まりではありませんが、セッターの引数に指定する変数は、フィールドと同じ名前を付けるケースが多いようです。
また、表からわかるとおり、一つのフィールドに対し、必ずしもセッターとゲッターが両方つくとは限りません。必要に応じ、セッターのみ、あるいはゲッターのみの場合もあります。
引数つきのコンストラクタ
SampleClass03.javaの9行目から11行目に、SampleClass03クラスのコンストラクタが定義されています。このコンストラクタには、引数が付いています。このように、コンストラクタは、他のメソッド同様、引数をつけることが可能です。このように、コンストラクタは、引数がついたものを指定することも可能です。このようなコンストラクタを使用する場合には、newをするときにも、引数を与える必要があります。
引数付きコンストラクタと、newの指定の方法↓
SampleClass03 s = new SampleClass03("HelloWorld."); ← 呼び出し方
クラスに、引数つきのコンストラクタが定義されている場合、引数なしのコンストラクタを呼び出すことはできません。ためしに、Sample702.javaの8行目のコメントを削除してください。次のようなエラーが出ます。
重複ローカル変数 s
コンストラクター SampleClass03() は未定義です
at day7.Sample702.main(Sample702.java:8)
これは、引数なしのコンストラクタが定義されていないという意味です。
デフォルトコンストラクタ
ところで、第6日目で紹介した、Sample01.javaには、コンストラクタがありませんでした。クラスにコンストラクタが存在しないのに、どうしてコンストラクタが呼び出せるのでしょうか?
SampleClass01.java(再掲)package day6; public class SampleClass01 { // フィールド int n = 10; String s = "field"; // メソッド int add(int a,int b){ return a + b; } String add(String s){ return this.s + s; } void showNum(){ System.out.println("n = " + n); } }
実は、このような場合、Javaでは、デフォルトコンストラクタと呼ばれる、見えないコンストラクタがあると考えます。このコンストラクタないでは、何も処理はされませんが、newで呼び出すのは、このコンストラクタであるというのが、Javaの考え方です。
図7-2.デフォルトコンストラクタ練習問題 : 問題5.