88524


現在、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]


CC BY-SA 4.0
2022-04-26T17:41:09.627
88522
2022-04-30T19:57:07.063
2022-04-30T19:57:07.063
51596
51596
question
java
オブジェクト指向によるthisの使い方


ここの `this.name`

[code]

    public Person(String name) {
        this.name = name;    
    }
    
[/code]

は、コンストラクターの引数として与えられるローカル変数 `name` と、フィールド変数として定義された

[code]

    public String name;
    
[/code]

の `name` とを区別して、フィールド変数の `name` であることを明示するためのものです。

要するに、this（このインスタンスの）`name` ですよ、という意味です。

一方、

[code]

    public void hello() {
        System.out.println(name);
    }
    
[/code]

こちらにおいては、引数としてローカル変数の name が存在するわけではないので、`this.` を付けて明示する必要がないだけです。実質、モノとしては
`this.name` と同じものです。

[code]

    public Person(String name) {
        this.name = name;    
    }
    
[/code]

の（`this.` なしの）`name` だけが、引数から与えられるローカル変数として、他とは違う実体のものです。


CC BY-SA 4.0
2022-04-26T18:33:15.433
88523
2022-04-26T18:33:15.433
7290
88522
answer


> `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`
でフィールドを参照できます。


CC BY-SA 4.0
2022-04-26T19:17:53.010
88524
2022-04-26T19:17:53.010
2808
88522
answer