Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 > Java基本 > クラス −6.コンストラクタ
更新日:2005/7/25
クラス−6.コンストラクタ
このページではクラスの主要構成要素の1つであるコンストラクタについて説明します。
コンストラクタの宣言方法
コンストラクタはオブジェクトを生成する際に必ず実行される初期化処理を記載した部分です。コンストラクタの宣言は以下の枠内のフォーマットで構成されています。アクセスレベルはコンストラクタが同一クラス内からしか実行できない、どのクラスからでも実行できるなどを指定するために使用します。アクセスレベルの詳細は本ページの別の項で詳しく行います。コンストラクタ名は属するクラスと同じ名前になります。(引数型 引数名)は初期化処理を実行する際に呼び出し元から渡される値の型とコンストラクタ内で使用される変数名を表します
アクセスレベル コンストラクタ名 (引数型 引数名)
コンストラクタ宣言における必須項目はコンストラクタ名 (引数型 引数名)です。コンストラクタ宣言時に付与できる修飾子はアクセスレベルのみです。クラス内にコンストラクタを宣言しない場合、コンパイル時に引数を持たず何の処理も行わないデフォルトコンストラクタと言うものが生成されます。クラス内に1つでもコンストラクタが宣言されている場合はデフォルトコンストラクタは生成されません
【例1】コンストラクタの宣言、使用例です。
class Calculate {
  private double syohizei;
  //(1)コンストラクタの宣言
  Calculate (double x) {
    syohizei = x;
  }
  //taxCaluculateメソッド
  int taxCalculate (int p) {
    return((int)(p * (1 + syohizei)));
  }
}

public class ExClass5 {
  public static void main(String[] args) {
    //(2)オブジェクトの生成、コンストラクタの実行
    Calculate goods = new Calculate(0.05);
    System.out.println("金額は" + 
                       goods.taxCalculate(100)); //(3)
  }
}

【解説1

(1). アクセスレベル無指定(デフォルト)、引数に引数型double、引数名xを持つコンストラクタを宣言しています。コンストラクタ内では引数に指定された値でメンバ変数syohizeiの初期化を行っています。
(2). Calculateクラスのオブジェクトgoodsの生成を行います。その際、引数に0.05を指定し、コンストラクタの呼び出しを行います。(1)で宣言したコンストラクタが実行され、メンバ変数syohizeiが値0.05で初期化されます。
(3). CalculateクラスのメソッドtaxCalculateを呼び出し、その結果の表示を行います。taxCalculateメソッド内では引数の値とメンバ変数syohizeiの値で消費税の計算を行い、計算結果を返します。
【実行結果1】
D:\JAVA>javac ExClass5.java

D:\JAVA>java ExClass5
金額は105

D:\JAVA>
複数のコンストラクタ
コンストラクタは引数の型や引数の数を変更することで1クラス内に複数宣言することができます。引数の型と引数の数が同じコンストラクタを1クラス内で複数宣言することはできません。コンパイルエラーとなります。

例えば、コンストラクタ内でいくつかのメンバ変数を初期化する場合、ある時はすべてのメンバ変数に対する値が指定され、またあるときは一部のメンバ変数に対する値のみ指定され、指定されなかったメンバ変数に対してはデフォルト値で初期化したいといったことがあります。このような時にコンストラクタを複数宣言します。すべてのメンバ変数に対する値が指定された時に使用するコンストラクタ、一部のメンバ変数に対する値のみ指定された時に使用するコンストラクタと言った形です。

例2では引数の型や引数の数が異なるコンストラクタが3つ宣言されています。引数を3つ持つコンストラクタと、引数が1つで引数型がint型のコンストラクタと、引数が1つで引数型がdouble型のコンストラクタです。コンストラクタ名は同じですがそれぞれ異なるコンストラクタとして動作します。

コンストラクタの参照は呼び出し元の引数の型、引数の数により決定されます。呼び出し元の引数が3つの場合は引数を3つ持つコンストラクタが、呼び出し元の引数がint型の場合は引数にint型を持つコンストラクタが参照されます。例2ではオブジェクトを生成する際、引数にdouble型の値を1つ指定しているため、double型の引数を1つ持つSetNumber(double c)コンストラクタが参照されます。
【例2】
public class SetNumber {
  private int numberA;
  private int numberB;
  private double numberC;
  //引数を3つ持つコンストラクタ
  SetNumber (int a, int b, double c) {
    numberA = a;
    numberB = b;
    numberC = c;
  }
  //int型の引数を1つ持つコンストラクタ
  SetNumber (int a) {
    numberA = a;
    numberB = 20;
    numberC = 250.35;
  }
  //double型の引数を1つ持つコンストラクタ
  SetNumber (double c) {
    numberA = 10;
    numberB = 20;
    numberC = c;
  }
  public static void main(String[] args) {
    //コンストラクタの呼び出しにdouble型の引数1つを指定
    SetNumber objectA = new SetNumber(110.55);
    ------その他の処理------
  }
} 
コンストラクタ内から同一クラスで宣言された別のコンストラクタを呼び出すこともできます。例2では3つのコンストラクタそれぞれでメンバ変数の初期化をしていましたが、この方法を使うと1つのコンストラクタでメンバ変数の初期化を行い、他の2つのコンストラクタではメンバ変数の初期化を行っているコンストラクタを呼び出すと言った処理ができるようになります。この方法を使用するためにはthisを使用します。

例3では引数を3つ持つコンストラクタでメンバ変数の初期化処理を記載しています。int型の引数を1つ持つコンストラクタとdouble型の引数を1つ持つコンストラクタではthisを使用し、引数を3つ持つコンストラクタを呼び出しています。コンストラクタ内でthisを使用する場合は文の一番初めに記載してください。それ以外の場所に記載した場合はコンパイルエラーとなります。

例3ではSetNumberクラスのオブジェクトobjectAを生成する時にコンストラクタを呼び出します。呼び出すコンストラクタの引数にはdouble型の値1つが設定されていますため、double型の引数を1つ持つコンストラクタが実行されます。コンストラクタ内ではthisの引数として、double型の値以外の引数にはデフォルト値を指定します。thisには引数が3つ指定されていますため、引数を3つ持つコンストラクタが実行され、メンバ変数の初期化処理が行われます。
関連ページ:thisの利用
【例3】
public class SetNumber {
  private int numberA;
  private int numberB;
  private double numberC;
  //引数を3つ持つコンストラクタ
  SetNumber (int a, int b, double c) {
    numberA = a;
    numberB = b;
    numberC = c;
  }
  //int型の引数を1つ持つコンストラクタ
  SetNumber (int a) {
    this(a, 20, 250.35);
  }
  //double型の引数を1つ持つコンストラクタ
  SetNumber (double c) {
    this(10, 20, c);
  }
  public static void main(String[] args) {
    //コンストラクタの呼び出しにdouble型の引数1つを指定
    SetNumber objectA = new SetNumber(110.55);
    ------その他の処理------
  }
} 
コンストラクタのアクセスレベル
コンストラクタを宣言する際、アクセスレベルを指定し、他のどのクラスからそのコンストラクタが使用できるかを決めることができます。同一クラス内からしかオブジェクトの生成を許さない場合はprivateアクセスレベルを指定するなどです。以下はコンストラクタで指定できるアクセスレベルとその説明です。
アクセスレベル
説明
public
すべてのクラスでコンストラクタを使用することができます。
protected
コンストラクタを宣言したクラスのサブクラスと、同じパッケージ内のクラスでのみコンストラクタを使用することができます。
指定なし
コンストラクタを宣言したクラスと同じパッケージ内のクラスでのみコンストラクタを使用することができます。
private
コンストラクタを宣言したクラス内でのみ、そのコンストラクタを使用することができます。
スーパークラスのコンストラクタ
クラスのページでクラスの継承を行う際、コンストラクタはサブクラスに継承されないと説明しました。サブクラスでスーパークラスのコンストラクタを使用したい場合はsuperを使用します。superはサブクラスのコンストラクタの一番初めに記載します。それ以外の場所に記載した場合はコンパイルエラーとなります。以下に例を記載します。
関連ページ:superの利用
【例4】コンストラクタ内でsuperを使用した例です。
class ExClass6 {
  private int memberA;
  //スーパークラスのコンストラクタ
  ExClass6(int a) {  //(3)
    memberA = a;
  }
  //showMemberメソッド
  void showMember(){
    System.out.println(memberA);
  }
}
public class subExClass6 extends ExClass6 {
  //superでスーパークラスのコンストラクタを呼び出し
  subExClass6(){  //(2)
    super(10);
  }
  public static void main(String[] args) {
    subExClass6 objectA = new subExClass6();  //(1)
    objectA.showMember();  //(4)
  }
}

【解説4

(1). クラスsubExClass6のオブジェクトobjectAを生成し、コンストラクタを呼び出します。
(2). コンストラクタ内でsuperを使用し、スーパークラスのコンストラクタを呼び出します。
(3). スーパークラスのコンストラクタで引数に指定された値に元づき初期化処理を行います。
(4). showMemberメソッドを使用し、初期化処理が行われたかの確認を行います。
【実行結果4】
D:\JAVA>javac subExClass6.java

D:\JAVA>java subExClass6
10

D:\JAVA>
コンストラクタ内で使用するthisとsuperに関して以下の3点の規定があります。
1. 1つのコンストラクタ内でthisとsuperの両方を記載することはできない。
2. thisとsuperの両方とも記載されていないコンストラクタではスーパ-クラスの引数無しのコンストラクタが呼び出される。
3. thisが記載されている時は、thisによって呼び出される先のコンストラクタでスーパークラスの引数無しのコンストラクタが呼び出される。
2、3のスーパークラスの引数無しのコンストラクタの呼び出しに関して注意点があります。継承を行った際、継承されたスーパークラスにおいて引数無しのコンストラクタが宣言されていない場合、サブクラスのコンストラクタ内でスーパークラスの引数無しのコンストラクタが呼び出された時にコンパイルエラーとなります。このエラーの対処策としてはスーパークラスに引数無しのコンストラクタを宣言します。Javaでは、すべてのクラスはスーパークラスとしてObjectクラスを継承してします。Objectクラスでは引数無しのコンストラクタが宣言されています。そのため、意図的に継承を行っていないクラスにおいてはこの注意点に関するコンパイルエラーは起こりません。
【例5】スーパークラスの引数無しのコンストラクタ呼び出しによってコンパイルエラーとなる例です。
class ExClass7 {
  private String memberA;
  //スーパークラスのコンストラクタ
  ExClass7(String s) {
    memberA = s;
  }
}
public class subExClass7 extends ExClass7 {
  private String memberB;
  //サブクラスのコンストラクタ
  subExClass7(String s) {  //(2)
    memberB = s;
  }
  public static void main(String[] args) {
    subExClass7 objectB = new subExClass7("test");  //(1)
  }
}

【解説5

(1). クラスsubExClass7のオブジェクトobjectBを生成し、コンストラクタを呼び出します。
(2). subExClass7(String s)コンストラクタではthisもsuperも使用されていませんので、スーパークラスの引数無しのコンストラクタを呼び出します。スーパークラスのExClass7では引数無しのコンストラクタは宣言されていませんのでコンパイルエラーとなります。
【実行結果5】
D:\JAVA>javac subExClass7.java
subExClass7.java:9: シンボルを解釈処理できません。
シンボル: コンストラクタ ExClass7 ( )  ←引数無しのコンストラクタが宣言されてない
位置 : ExClass7 の クラス
subExClass7(String s) {
              ^

エラー 1 個

D:\JAVA >



このページのトップへ
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道_CopyrightJavaの道