オブジェクト指向によるthisの使い方


現在、MainクラスとPersonクラスを生成し、`this.name`
で名前をコンストラクタに設定し、出力するプログラムを作っています。そこで、`this` について質問があります。

以下のコードでインスタンスを生成したときに `this.name = name` と定義し、`System.out.println(name);`
と書くことでAくんとBくんの名前を出力できますが、 `println(name)` の所を `println(this.name)`
と入力しても、同様にAくんとBくんの名前が出力されます。

`this.name` と書くのと、`name` と書き出力するのでは、なにか違いはあるのでしょうか？

* * *

**Main.java:**

[code]

    public class Main {
        public static void main (String args[]) {
            Person person1 = new Person("Aくん"); 
            person1.hello();
            Person person2 = new Person("Bくん");
            person2.hello();
        }
    }
    
[/code]

**Person.java:**

[code]

    class Person{
        public String name;
    
        public Person(String name) {
            this.name = name;    
        }
    
        public void hello() {
            System.out.println(name);
        }
    }
    
[/code]




> `this.name`と書くのと、`name`と書き出力するのでは、なにか違いはあるのでしょうか？

**`hello()` メソッドの中では** どちらも同じものです。つまり、違いはありません。

* * *

`name` のようなものを単純名(simple name)、 `this.name` のようなものを修飾名(qualified name)と呼びます。

同名の変数が存在しない場合、その変数は単純名で参照することができます。

他方、同名の変数が複数存在する場合、単純名で参照できるのはそのうちどれかひとつで、それ以外は単純名では参照できなくなります(shadowing)。shadowingされた変数は修飾名で参照する必要があります。  
このときの、単純名で参照できるのはどれなのかは仕様([6.4.1.
Shadowing](https://docs.oracle.com/javase/specs/jls/se18/html/jls-6.html#jls-6.4.1))で決まっています。

今回の例で言うと、`name` という名前は、

  * フィールド
  * コンストラクタの仮引数

の2つで用いられています。

従って、コンストラクタでは、次のルールで変数を参照することになります。

  * 単純名`name`は仮引数を指す(前述の仕様により)
  * フィールドはshadowingされる
  * shadowingされたフィールドを参照するためには修飾名(今回の場合は `this.name`)を用いる必要がある

これに対し、 `hello()` メソッドでは(コンストラクタと異なり) `name` はフィールドのみを指すので、そのまま単純名 `name`
でフィールドを参照できます。




> `this.name`と書くのと、`name`と書き出力するのでは、なにか違いはあるのでしょうか？

**`hello()` メソッドの中では** どちらも同じものです。つまり、違いはありません。

* * *

`name` のようなものを単純名(simple name)、 `this.name` のようなものを修飾名(qualified name)と呼びます。

同名の変数が存在しない場合、その変数は単純名で参照することができます。

他方、同名の変数が複数存在する場合、単純名で参照できるのはそのうちどれかひとつで、それ以外は単純名では参照できなくなります(shadowing)。shadowingされた変数は修飾名で参照する必要があります。  
このときの、単純名で参照できるのはどれなのかは仕様([6.4.1.
Shadowing](https://docs.oracle.com/javase/specs/jls/se18/html/jls-6.html#jls-6.4.1))で決まっています。

今回の例で言うと、`name` という名前は、

  * フィールド
  * コンストラクタの仮引数

の2つで用いられています。

従って、コンストラクタでは、次のルールで変数を参照することになります。

  * 単純名`name`は仮引数を指す(前述の仕様により)
  * フィールドはshadowingされる
  * shadowingされたフィールドを参照するためには修飾名(今回の場合は `this.name`)を用いる必要がある

これに対し、 `hello()` メソッドでは(コンストラクタと異なり) `name` はフィールドのみを指すので、そのまま単純名 `name`
でフィールドを参照できます。

