this キーワード
代入したはずなのに、null のまま
前のレッスンのコンストラクタは、引数名を n a と 1 文字にして、フィールド名とぶつからないようにしていました。ただ、これは読む側にはつらい書き方です。n が名前なのか番号なのか、宣言まで戻らないと分かりません。
そこで引数名をフィールドと同じ name weight に揃えると、今度は別の問題が起きます。
Java
class Cat {
String name;
int weight;
Cat(String name, int weight) {
name = name;
weight = weight;
}
}
Cat c = new Cat("タマ", 3);
System.out.println(c.name); // nullコンパイルは通ります。実行もできます。それなのに null が出ます。
近い方の name が勝つ
Cat(String name, int weight) の中には name が 2 つあります。フィールドの name と、引数の name です。同じ名前が 2 つある場所で Java が選ぶのは、より近い方、つまり引数の name です。
だから name = name; は「引数の name に、引数の name を入れ直す」だけの、何も起きない文になります。フィールドは一度も触られていないので null のままです。エラーが出ないぶん、原因にたどり着くまでが長くなります。
this. を付けて、遠い方を名指しする
このとき使うのが this です。
Java
Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}this は「いま作られている、この 1 匹」を指す言葉です。this.name と書けば、近くにある引数を飛び越して、その猫が持っているフィールドの name に届きます。右辺の name は引数のままなので、1 行が「フィールドの name に、引数の name を入れる」と素直に読めます。
this. はコンストラクタ専用の道具ではありません。フィールドを書き換えるふつうのメソッドでも、引数に同じ名前を使いたければ同じように付けます。
Java
void rename(String name) {
this.name = name;
}引数名を短縮せずに済むので、結果としてコードは読みやすくなります。
thisが使えるのは、インスタンスに属するコンストラクタとメソッドの中だけです。staticの付いたメソッドの中で書くとnon-static variable this cannot be referenced from a static contextというエラーになります。staticは特定の 1 匹ではなくクラスそのものに属するので、指す相手がいないからです。
やってみよう
右のエディタで describeBook(String title, int price) を完成させます。本のタイトルと値段を受け取って、表示用の 1 本の文字列にして返すメソッドです。半角スペースやカッコの位置は、課題の要件どおりに 1 文字ずつ合わせてください。
このメソッドは static なので、中では this を使えません。緑になったら、Book クラスを自分で書いて、タイトルと値段をコンストラクタで this. 付きで受け取り、同じ文字列を返すメソッドを持たせる形に組み直してみてください。this. を 1 か所わざと外して、null や 0 が出るところまで見ておくと、次に同じバグを踏んだとき一瞬で気づけます。
要件
- クラス名は
Solution、メソッド名はdescribeBookのままにすること - 戻り値は
title + " (¥" + price + ")"の書式のString - 半角スペース、半角カッコ
()、円記号¥の位置と種類を正確に揃えること
入出力例
describeBook("Java入門", 2000) → "Java入門 (¥2000)"
describeBook("SQL基礎", 1500) → "SQL基礎 (¥1500)"
describeBook("無題", 0) → "無題 (¥0)"
describeBook("Effective Java", 4400) → "Effective Java (¥4400)"