thisのコードトレース

thisは現在のインスタンスを表す参照です。同名引数とフィールドを区別し、現在の実体のメソッドを呼ぶ、引数として渡す、戻り値にする使い方を確認します。this(...)のコンストラクタ呼出しとは構文の役割が異なります。

この単元で学ぶこと

  • thisが表す実体を特定する
  • フィールド・引数・別実体への参照を区別する
  • this式とコンストラクタ委譲を区別する

本文解説

呼出しごとのthisを追う Box aとbが別実体ならa.add(1);b.add(2);のthisは異なります。一方b=aと代入した後なら同じ実体です。メソッド名や変数名だけでなく、呼出しの時点で受け手参照がどこを指すかを更新して追います。

仮引数へthisの値を代入 int read(int n){n=this.n;return n;}はフィールド値をローカルな仮引数へコピーして返します。呼出し側の引数変数は変わりません。この読み出しとthis.n=nによる状態書込みは向きが逆です。

同じクラスのprivate Boxのメソッド内ならother.nが別Boxのprivateフィールドでもアクセスできます。privateはその実体自身だけを意味する制約ではなく、宣言したクラス等の許可された文脈でのアクセス制約です。別トップレベルのMainからの直接アクセスとは違います。

共有参照での交換 void swap(Box other){int t=this.n;this.n=other.n;other.n=t;}は二つの状態を交換します。otherがthisと同じ実体なら元の値のままです。別実体か同一実体かで状態図を分ければ、同じコードの結果を説明できます。

チェーン中の別実体 Box add(){n++;return new Box();}の場合、b.add().add()の二回目は最初の呼出しが返した別実体です。元bは一回だけ増えます。メソッドチェーンという書式だけで同じ対象を使い続けると決めてはいけません。

引数に渡したthisの付替え helper.reset(this)で受け手を渡しても、helper側の仮引数をnew Box()へ付け替えるだけなら元の実体は変わりません。thisも値渡しされる参照値であり、参照先変更と参照変数変更の区別は通常の変数と同じです。

this式とthis呼出し this.nはフィールドアクセス、this.add()はインスタンスメソッド呼出し、this(3)は同一クラス内の別コンストラクタ呼出しです。最後だけはJava 11のコンストラクタ先頭に限られます。丸括弧の位置とメンバー名の有無を読み分けます。

異なる引数をまとめる初期化 Box(){this(2,3);}Box(int a,int b){this.n=a+b;}は引数なし生成も共通の初期化へまとめます。this(...)から戻った後の追加処理は同じ実体を使います。コードの重複を減らせますが、循環や先頭制約を守る必要があります。

図解

同名引数を区別する
thisはクラス全体やすべての実体ではなく、現在の一つの受け手。

重要ポイント

  • this.nは現在の受け手のフィールドn。
  • thisはインスタンスメソッドやコンストラクタの文脈で使う。
  • staticメソッドではthisを使えない。
  • return thisは同じ実体への参照を返す。

間違えやすい点

  • thisを新しい実体を作る演算と考えない。
  • this.n=nの左右を同じ変数と思わない。
  • this(...)を普通のメソッド内で呼ばない。

用語解説

this
現在実行中のインスタンスメンバーの受け手を表す参照。
受け手
obj.method()でobjが指す呼出し対象の実体。
メソッドチェーン
参照を返すメソッドの結果へ続けてメソッドを呼ぶ記述。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。