Java:Class.this


112

このようなJavaプログラムがあります。

public class LocalScreen {

   public void onMake() {
       aFuncCall(LocalScreen.this, oneString, twoString);
   }
}

はどういうLocalScreen.this意味aFuncCallですか?

回答:


169

LocalScreen.this指し、this包含するクラスの。

この例はそれを説明するはずです:

public class LocalScreen {
    
    public void method() {
        
        new Runnable() {
            public void run() {
                // Prints "An anonymous Runnable"
                System.out.println(this.toString());
                
                // Prints "A LocalScreen object"
                System.out.println(LocalScreen.this.toString());
                
                // Won't compile! 'this' is a Runnable!
                onMake(this);
                
                // Compiles! Refers to enclosing object
                onMake(LocalScreen.this);
            }
            
            public String toString() {
                return "An anonymous Runnable!";
            }
        }.run();
    }
    
    public String toString() { return "A LocalScreen object";  }
    
    public void onMake(LocalScreen ls) { /* ... */ }
    
    public static void main(String[] args) {
        new LocalScreen().method();
    }
}

出力:

An anonymous Runnable!
A LocalScreen object

この投稿は、こちらの記事に書き直されました。


次のようなものがあるとしたらpublic class a { private class a { public void run() { System.out.println(a.this.toString()); } } どうでしょう。a.thisrun()を参照しなければならない囲む aさんthis。私は正しいですか?(これは、縮小されたコードがOSX Kindle Previewerアプリの.jarファイルにある方法です。私が見ているものを理解しようとしているだけです。)
Matt Mc

Javaでは、内部クラスはそれを含むクラス(JLS 8.1)と同じ名前を持たない可能性があるため、このa.this例では定義されていません。この制約がバイトコードに当てはまるかどうかはわかりません。そうでないかもしれない。
aioobe 2015

56

これは、this外部LocalScreenクラスのインスタンスを意味します。

this修飾子なしで書き込むと、呼び出しが含まれる内部クラスのインスタンスが返されます。


4
まだよくわかりません。「これ」と比較して「LocalScreen.this」としてコード化した場合の違いは何ですか?私は両方をテストし、コンパイラーは「LocalScreen.this」のみを受け入れました。aFuncCallの最初のパラメーターは、「Somethig」の親クラスであるaParentクラスを想定しています。
ジョニージャズ

1
私もこれについて知りたいです。これが何を意味するのか詳細を教えてもらえますか?上記のコードで定義されている内部クラスはありません。すべてのJava関数には、それがメンバーとなっているクラスとは別の匿名クラスが関連付けられていますか?
poundifdef 2011

4
@rascher:内部クラスが使用されています。OPはそれらをコードスニペットに含めませんでした。この構文は、非静的内部クラスでのみサポートされています。
SLaks、2011

Javaの公式ドキュメントへのリンクを提供してくれてうれしいです。
Krzysztof Tomaszewski 2018年

14

コンパイラはコードを受け取り、それを次のように実行します。

public class LocalScreen 
{
    public void method() 
    {
        new LocalScreen$1(this).run;
    }

    public String toString() 
    {
        return "A LocalScreen object"; 
    }

    public void onMake(LocalScreen ls) { /* ... */ }

    public static void main(String[] args) 
    {
        new LocalScreen().method();
    }
}

class LocalScreen$1
     extends Runnable
{
    final LocalScreen $this;

    LocalScreen$1(LocalScreen $this)
    {
        this.$this = $this;
    }

    public void run() 
    {
        // Prints "An anonymous Runnable"
        System.out.println(this.toString());

        // Prints "A LocalScreen object"
        System.out.println($this.toString());

        // Won't compile! 'this' is a Runnable!
        //onMake(this);

        // Compiles! Refers to enclosing object
        $this.onMake($this);
    }

    public String toString() 
    {
        return "An anonymous Runnable!";
    }
}

ご覧のとおり、コンパイラが内部クラスを取得すると、外部クラスに変換されます(これは、内部クラスを理解するためにVMを変更する必要がないように、かなり前に行われた設計上の決定でした)。

非静的内部クラスが作成されると、外部クラスのメソッド/アクセス変数を呼び出すことができるように、親への参照が必要になります。

内部クラスであったもののthisは適切なタイプではありません。onMakeメソッドを呼び出すための適切なタイプを取得するには、外部クラスにアクセスする必要があります。


べきではないnew LocalScreen$1().run;ことnew LocalScreen$1(this).run;
Diskutant 2015

これは質問に対する過小評価された答えです。面白いもの。
Pinkerton 2017年

12

Class.this外部クラスのインスタンスへのアクセスを許可します。次の例を参照してください。

public class A
{
  final String name;
  final B      b;
  A(String name) {
    this.name = name;
    this.b = new B(name + "-b");
  }

  class B
  {
    final String name;
    final C      c;
    B(String name) {
      this.name = name;
      this.c = new C(name + "-c");
    }

    class C
    {
      final String name;
      final D      d;
      C(String name) {
        this.name = name;
        this.d = new D(name + "-d");
      }

      class D
      {
        final String name;
        D(String name) {
          this.name = name;
        }

        void printMe()
        {
          System.out.println("D: " + D.this.name); // `this` of class D
          System.out.println("C: " + C.this.name); // `this` of class C
          System.out.println("B: " + B.this.name); // `this` of class B
          System.out.println("A: " + A.this.name); // `this` of class A
        }
      }
    }
  }
  static public void main(String ... args)
  {
    final A a = new A("a");
    a.b.c.d.printMe();
  }
}

その後、取得します。

D: a-b-c-d
C: a-b-c
B: a-b
A: a

これまでによく説明された唯一の答え...それは確かに「Class.thisは外部クラスのインスタンスへのアクセスを許可する」であり、「Class.thisは外部クラスのthisへのアクセスを許可する」のようなものではありません。クラスは、「これは」、インスタンスのみが...自分自身を参照するために持っていない
Żabojad

-2

あなたの混乱は何ですか?私は今問題に遭遇しています、それらを区別するために特別なシーンが必要です。

class THIS {
  def andthen = {
    new THIS {
      println(THIS.this.## + ":inner-THIS.this.##")
      println(this.## + ":inner-this.##")
      new THIS {
        println(THIS.this.## + ":inner-inner-THIS.this.##")
        println(this.## + ":inner-this.##")
      }
    }
  }
  def getInfo = {
    println(THIS.this.## + ":THIS.this.##")
    println(this.## + ":this.##")
  }
}

ハッシュコード(。##)を使用するTHIS.thisthis、新しいTHIS操作の差分を確認できます。

Scalaコンソールでテストする:

scala> val x = new THIS
x: THIS = THIS@5ab9b447

scala> val y = x.andthen
1522119751:inner-THIS.this.##
404586280:inner-this.##
1522119751:inner-inner-THIS.this.##
2027227708:inner-this.##
y: THIS = THIS$$anon$1@181d7f28

scala> x.getInfo
1522119751:THIS.this.##
1522119751:this.##

THIS.this常にval xによって参照される外部THISクラスを指しthisますが、匿名の新しい操作を超えています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.