this キーワード

コンストラクタやメソッドの中で、インスタンス自身への参照であるthisというキーワードを使うことができます。 ここではthisの役割について学習していきましょう。

インスタンス自身への参照

Robotクラス【第6版】では、名前を仮引数として受け取るコンストラクタは次のようになっていました。

    Robot(String n){
        name = n;  battery = 0;  x = 0;
    }

ここで仮引数のnをもっと意味の分かりやすいnameに変えて次のようにしたいところです。

    Robot(String name){
        name = name;  battery = 0;  x = 0;
    }

ところが、フィールドと同じ名前の仮引数やローカル変数を持つコンストラクタの本体では、フィールド名は仮引数またはローカル変数の名前と解釈されてしまいます。 そのため name = name; のどちらのnameも仮引数を表すことになるのです。 つまり、仮引数の値を仮引数に代入していることになり、全く意味がありません。

そこで、代入される方のnameにthis.を付けてみましょう。

    Robot(String name){
        this.name = name;  battery = 0;  x = 0;
    }

thisとは、コンストラクタによって初期化されているインスタンス自身への参照です。 従って、this.nameはインスタンスのフィールドを表すことになります。 これで、仮引数nameの値がフィールドのnameに代入されることになります。

同様のことがメソッドについても言えます。 Robotクラス【第6版】では、名前のセッターメソッドは次のようになっていました。

    void setName(String n){
        name = n;
    }

これをthisを使って次のように書き換えることができます。

    void setName(String name){
        this.name = name;
    }

thisはメソッドを中に含むインスタンス自身への参照です。 そして、this.nameはそのインスタンスのフィールドということになります。

バッテリー残量のセッターメソッドは次のようになっていました。

    void setBattery(int btry){
        if(btry >= 0){
            battery = btry;
        }else{
            battery = 0;
        }
    }

これも次のように書き換えられます。

    void setBattery(int battery){
        if(battery >= 0){
            this.battery = battery;
        }else{
            this.battery = 0;
        }
    }

nやbtryからnameやbatteryというそのものずばりの仮引数になって分かりやすくなりましたね。 フィールド名とは違う名前をいちいち考える必要もなくなり、開放感さえ感じられるでしょう。 ただし、フィールドの方にthis.を付け忘れないように注意しましょう。

英語のthisは「これ」「この」という意味です。

RobotTest07.javaはthisを使ってRobotTest06.javaを書き換えたプログラムです。 変更箇所はRobotクラスの引数の有る二つのコンストラクタと二つのセッターメソッドだけです。 テスト用クラスのmainメソッドは何も変わっていません。

RobotTest07.java
//ロボットクラス【第7版】
class Robot {
    private String name;    //名前
    private int battery;    //バッテリー残量
    private int x;    //x座標
    
    /*---- コンストラクタ ----*/
    Robot(){ }
    
    Robot(String name){
        this.name = name;  battery = 0;  x = 0;
    }
    
    Robot(String name, int battery){
        this.name = name;  setBattery(battery);  x = 0;
    }
    
    /*---- バッテリー残量を取得する ----*/
    int getBattery(){
        return battery;
    }
    
    /*---- 名前を設定する ----*/
    void setName(String name){
        this.name = name;
    }
    
    /*---- バッテリー残量を設定する ----*/
    void setBattery(int battery){
        if(battery >= 0){
            this.battery = battery;
        }else{
            this.battery = 0;
        }
    }
    
    /*---- x軸方向に歩く ----*/
    boolean walkX(int dx){
        int d = dx >= 0 ?  dx : -dx;    //dxの絶対値をdに代入しておく。
        if(d <= battery){
            x += dx;
            battery -= d;
            return true;
        }else{
            return false;
        }
    }
    
    /*---- 状態を表示する ----*/
    void showStatus(){
        System.out.println("現在のx座標: " + x);
        System.out.println("バッテリー残量: " + battery);
    }
    
    /*---- 名前と状態を表示する ----*/
    void show(){
        System.out.println("名前: " + name);
        showStatus();
    }
}

//ロボットクラス【第7版】のテスト用クラス
class RobotTest07 {
    public static void main(String[] args) {
        Robot robot1 = new Robot();
        //robot1.name = "ロボ太郎";    //private宣言されたフィールドへの代入
        //robot1.battery = 100;    //private宣言されたフィールドへの代入
        robot1.setName("ロボ太郎");
        robot1.setBattery(100);
        
        Robot robot2 = new Robot("ロボ子");
        robot2.setBattery(-90);
        if(robot2.getBattery() == 0)
            robot2.setBattery(90);
        
        robot1.show();    System.out.println();
        robot2.show();
    }
}

実行結果もRobotTest06と同じです。

RobotTest07の実行結果
名前: ロボ太郎
現在のx座標: 0
バッテリー残量: 100

名前: ロボ子
現在のx座標: 0
バッテリー残量: 90

thisがインスタンス自身を参照する様子を示すのが図 10-13です。

図 10-13 : thisでインスタンス自身を参照する

Robotクラス【第7版】では、フィールドと仮引数の名前が同じになっている場合だけ、フィールドにthis.を付けました。 しかし、実際にはいつでも付けることができるのです。 従って、次のようにgetBatteryメソッドでbatteryフィールドにthis.を付けても何ら問題はありません。

    int getBattery(){
        return this.battery;
    }

また、フィールドだけではなく、メソッドの呼び出しにもthis.を付けることができます。 例えば、showメソッドの本体でshowStatusメソッドを次のような形で呼び出すことができます。

    void show(){
        System.out.println("名前: " + name);
        this.showStatus();
    }

コンストラクタとメソッドでは、それを含んでいるインスタンス自身への参照であるthisを使うことができる。