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.nは現在の受け手のフィールドn。
- thisはインスタンスメソッドやコンストラクタの文脈で使う。
- staticメソッドではthisを使えない。
- return thisは同じ実体への参照を返す。
間違えやすい点
- thisを新しい実体を作る演算と考えない。
- this.n=nの左右を同じ変数と思わない。
- this(...)を普通のメソッド内で呼ばない。
用語解説
- this
- 現在実行中のインスタンスメンバーの受け手を表す参照。
- 受け手
- obj.method()でobjが指す呼出し対象の実体。
- メソッドチェーン
- 参照を返すメソッドの結果へ続けてメソッドを呼ぶ記述。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。