せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Java】Hoge.thisってなんだ? パーフェクトJava学習感想文 その5

パーフェクトJavaを読んで改めてJavaを振り返り中。


経緯については学習記録その1をご参照ください。

以下、学んだこと。

 

Hoge.thisってなんだ?

synchronizedの章で出てきた一節。

thisって、レシーバーだな、
くらいの認識しかなかったので改めて確認してみる

 

thisとは

Javaの言語仕様↓

thisというキーワードはインスタンスメソッドかコンストラクタの本体において,又はクラスのインスタンス変数の初期化子においてのみ使用される。

http://www.y-adagio.com/public/standards/tr_javalang/15.doc.htm#31980

なるほど。
thisは予約語か。

 

キーワードthisはインスタンスメソッドが呼び出されたオブジェクト(15.11)への,又は生成されたオブジェクトへの参照値を示す。 thisの型は,内部でキーワードthisが出現するクラスCとする。

なるほど。

だから、例えばこういうコード↓

public class Test {
  private class Hoge {
    void method1(){
      System.out.println(Test.this);
      System.out.println(this);
    }
  }
  public static void main(String[] args) {
    Hoge hoge = new Test().new Hoge();
    hoge.method1();
    Hoge hoge2 = new Test().new Hoge();
    hoge2.method1();
  }
}

■実行結果

Test@2f9ee1ac
Test$Hoge@67f1fba0
Test@3fbefab0
Test$Hoge@133c5982

Test.thisは、実行しているコンテキストの外部クラス(Test)の
インスタンスの参照値を取得してる。

 
Javaの仕様にもこのthisの記述があった

The value of an expression of the form ClassName.this is the n'th lexically enclosing instance of this.
It is a compile-time error if the current class is not an inner class of class C or C itself.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.3

ClassName.this ってところね。
 
ふむふむ。自クラスか内部クラスでしか使えない。


 
なぜ、Test.thisのロックを取ることで排他制御を実現できているかも、
以下のコードを見れば納得。

public class Test {  
  private class Hoge {
    void method1(){
      System.out.println(Test.this);
      System.out.println(this);
    }
  }
  public static void main(String[] args) {
    Test test = new Test();
    test.method();
    test.method();
  }
  void method(){
    new Hoge().method1();
  }
}

 
■実行結果

Test@2f9ee1ac
Test$Hoge@67f1fba0
Test@2f9ee1ac
Test$Hoge@3fbefab0

method1のレシーバーは異なる(呼び出しするのは常にnewしたHogeオブジェクトだから当然)けど、methodのレシーバーは同じオブジェクト。
だから、Test.thisのロックを取ることで排他制御を実現できる。