第16講・STEP 03

メンバメソッドって何? thisの意味

前回は、オブジェクトが持つ名前や生年月日を設定しました。今回はHumanクラスに「食べる」という振る舞いを追加します。eat()を呼んで満腹度を変えながら、メンバメソッドとthisの意味を見ていきましょう。

メンバメソッドとは?

 前々回の【Java】オブジェクトって何?で、Humanクラスを書いて、それをnewすることでHumanオブジェクトを作りました。Humanクラスはこんなのでした。

Human.java

public class Human{
    String name;
    int birthday;
}

 このクラスから作られたインスタンスはnameとbirthdayというデータを持っています。ここまでにHumanクラス自身で宣言したメンバは、nameとbirthdayの二つです。

 今回はここに新たなメンバを追加していきたいと思います。nameとbirthdayは変数(データ)ですが、今回新たに追加するメンバはメソッドです。

 変数でもメソッドでもそのクラスのメンバの一員です。変数はそのオブジェクトのデータを表すのに対して、メソッドはそのオブジェクトの振る舞いを表します。

 人間なら誰でも何かしら食べますよね。ということでHumanオブジェクトの振る舞いとして、eat()メソッドを追加します。

Human.java

public class Human{
    String name;
    int birthday;
    void eat(){}
}

 出来ました。

 このメソッドは戻り値を返さないようにするので「void」をメソッド名の前につけて、「eat( )」その後ろに{ }波かっこを書きます。これはメソッドの定義の形ですね。その波かっこの中にこのメソッドの内容を定義するんでした(参考:【Java】 メソッドの定義と呼び出し)。

今までのメソッドにはstaticを付けていましたが、今回のeat()には付けません。eat()は、特定のインスタンスに対して呼び出すインスタンスメソッドです。この講ではこうしたメソッドを扱います。staticを付けたメソッドとの違いは、後の講で詳しく説明します。

 eat()メソッドの中身は今のところ何も定義していません。まずはこの形を理解してください。これでHumanクラス自身で宣言したメンバは3つになりました。変数nameとbirthday、それにeat()メソッドです。

 さらにもう一つメンバを追加します。満腹度を示すデータです。満腹度は整数で表すことにしますのでint型の変数「manpukudo」をメンバに追加しましょう。名前がかっこ悪くて申し訳ないです。。いい英語が思いつかないので日本語で行きます。

Human.java

public class Human{
    String name;
    int birthday;
    int manpukudo;

    void eat(){}
}

 メンバ変数とメンバメソッドは分けて書いた方が見やすいので、上の方にメンバ変数はかためて書いておきましょう。さらに間を一列空けて書いたりしたら見やすくてGood。

メンバメソッドを定義する

 ではHumanクラスのメンバメソッドであるeat()メソッドを定義していきます。食べたらお腹が満たされるので、eat()メソッドが実行されると満腹度を表す「manpukudo」の数値が上がるようにします。なんぼ上がるかって?とりあえず適当に60上がることにしましょう。単位とか余計なことは考えずに。(笑)

Human.java

public class Human{
    String name;
    int birthday;
    int manpukudo;

    void eat(){
        this.manpukudo += 60;
    }
}

 はい、出ました。「this」です。初心者を苦しめるやつです。と言ってもそんな大したことないのでサクッとやっつけましょう。

 「this」は日本語で「これ」とか「この」という意味なのは皆さんご存知かと思いますが、この場合、「このインスタンス」という意味になります。そして半角の「.」を日本語の「の」と考えると、つなげて「this.」で「このインスタンスの」という意味になります。

つまりこのeat()メソッドの定義部分は「このインスタンスの満腹度を60上げる」という処理になります。this.manpukudo += 60;は、this.manpukudo = this.manpukudo + 60;と同じ意味です。

 案ずるより産むが易しです。実際やってみましょう。Humanクラスには、上記のように4つのメンバを自分で宣言した状態です。mainメソッドを持つHumanTestクラスでこのHumanクラスをインスタンス化して、実際にeat()メソッドも使ってみます。ここからはHumanTestクラスですよ。ごっちゃにならないように。

HumanTest.java

public class HumanTest{
    public static void main(String[] args){
        Human human = new Human();
        human.name = "ノブオ";
        human.birthday = 19770101;

        Human human2 = new Human();
        human2.name = "アヤネ";
        human2.birthday = 20110101;

        human.eat();   //ノブオ1回目の食事
        human.eat();   //ノブオ2回目の食事

        human2.eat();  //アヤネ1回目の食事
    }
}

 前回やりましたが、メンバ変数にアクセスするには、

オブジェクトを参照する変数.メンバ変数

この形でした。インスタンスメソッドも、参照する変数の後ろに「.」を付けて指定します。メソッドを呼ぶ場合は、さらにメソッド名の後ろに( )を付けます。

オブジェクトを参照する変数.メソッド名();

 「human.eat()」でノブオさんが食事したことになります。同じく「human2.eat()」でアヤネさんに食事させたわけです。

 上記ではノブオさんは2回も食事しています。アヤネさんは1回です。さて、それぞれの満腹度はどうなっているでしょうか?出力してみましょう。

HumanTest.java

public class HumanTest{
    public static void main(String[] args){
        Human human = new Human();
        human.name = "ノブオ";
        human.birthday = 19770101;

        Human human2 = new Human();
        human2.name = "アヤネ";
        human2.birthday = 20110101;

        human.eat();   //nobuo1回目の食事
        human.eat();   //nobuo2回目の食事

        human2.eat();  //ayane1回目の食事

        System.out.print(human.name + "の満腹度:");
        System.out.println(human.manpukudo);
        System.out.print(human2.name + "の満腹度:");
        System.out.println(human2.manpukudo);
    }
}

Human.javaとHumanTest.javaを同じsrcの直下(パッケージを指定している場合は同じパッケージ)に置き、HumanTestのmainメソッドを実行します。実行結果はコンソールに表示されます。

実行結果
ノブオの満腹度:120
アヤネの満腹度:60

 こうなります。
 ノブオさんは2回食事したので満腹度が120になっています。アヤネさんは1回だけなので満腹度60です。

 それぞれのインスタンスごとに満腹度というデータを持っていて、それぞれのeat()メソッドを実行することで、それぞれの満腹度を+60しているわけです。

「this.manpukudo += 60」の意味が分かりましたでしょうか?eat()メソッドは、自分自身のデータ(manpukudo)を60増やすという処理を行います。「自分自身の」という意味で「this.」が使われているわけです。

メンバ変数の初期値

 ところで、2回食事をしたノブオが120で、1回食事をしたアヤネが60ということは、メンバ変数manpukudoの初期値は「0」だったということが分かりますね。

 manpukudoには明示的な初期値を書いていませんでした。このようなint型のインスタンス変数は、インスタンスを作る際に既定値の0で初期化されます。なので、manpukudoの初期値は「0」なんです。

 さらに、boolean型のフィールドの既定値はfalse、Stringなど参照型のフィールドの既定値はnullです。nullは「どのオブジェクトも参照していない」ことを表し、空文字列の""とは違います。mainメソッドなどの中で宣言するローカル変数には、この既定値による初期化はありません。

 なので、nameとbirthdayはインスタンスを作った時点では「null」と「0」なのですが、「human.name = “ノブオ”;」「human.birthday = 19770101;」でそれぞれの値を後から書き換えていることになります。

 さて、勘の良い方はお気づきかと思いますが、名前や生年月日をインスタンスを作ってから設定するのではなく、インスタンスを作る時点、つまりnew()するときに決定したいですよね?

 今回のように誰を表すインスタンスかが決まっているなら、名前と生年月日を最初から設定しておきたいところです。

 名無しのインスタンスを作ってから名前と生年月日を入力するのではなく、「ノブオという名の1977年1月1日生まれの人間」を表すインスタンスを初期状態として作るということです。

 それが実は簡単にできるんです。コンストラクタというのを使えば、インスタンスの初期状態を自由に操ることができます。次回、「コンストラクタって何?」で解説します。

目次へ

質問・コメント

読み込み中

この記事についての質問や、学習して気づいたことをお寄せください。

コメントを書く

投稿フォームを準備しています。

コメントと一緒に公開される名前です。
3,000文字以内。パスワードなどの個人情報は書き込まないでください。

コメントは送信後すぐに公開されます。

この記事のコメント

旧サイトに寄せられたコメントも当時の投稿内容のまま掲載しています。現在の記事では変更している内容や、旧環境についてのやり取りも含まれます。

コメントを読み込んでいます。