Java: Class.this

У меня есть программа на Java, которая выглядит следующим образом.

public class LocalScreen {

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

Что значит LocalScreen.this означает в aFuncCall?

5 ответов

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

Этот пост был переписан как статья здесь.

Это означает this экземпляр внешнего LocalScreen учебный класс.

Пишу this без квалификатора вернет экземпляр внутреннего класса, внутри которого находится вызов.

Компилятор берет код и делает с ним что-то вроде этого:

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!";
    }
}

Как вы можете видеть, когда компилятор берет внутренний класс, он конвертирует его во внешний класс (это было проектное решение, принятое долгое время назад, так что виртуальные машины не нужно было менять для понимания внутренних классов).

Когда создается нестатический внутренний класс, ему нужна ссылка на родительский класс, чтобы он мог вызывать методы / переменные доступа внешнего класса.

Это внутри того, что было внутренним классом, не является правильным типом, вам нужно получить доступ к внешнему классу, чтобы получить правильный тип для вызова метода onMake.

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 {
  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.this а также 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 выходит за рамки анонимной новой операции.

Другие вопросы по тегам