【问题标题】:Java: Class.thisJava:类.this
【发布时间】:2011-07-28 15:58:33
【问题描述】:

我有一个类似这样的 Java 程序。

public class LocalScreen {

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

LocalScreen.thisaFuncCall 中是什么意思?

【问题讨论】:

    标签: java class this


    【解决方案1】:

    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
    

    本帖已改写为文章here

    【讨论】:

    • 如果你有类似的东西怎么办:public class a { private class a { public void run() { System.out.println(a.this.toString()); } }我想这是同样的事情; run() 中的a.this 必须引用封闭 athis。我对吗? (这就是 OSX Kindle Previewer 应用程序的 .jar 文件中的缩小代码,我只是想了解我在看什么。)
    • 在 Java 中,内部类的名称可能与其任何封闭类 (JLS 8.1) 的名称不同,因此您的示例中的 a.this 未定义。我不知道这个约束是否适用于字节码。也许不是。
    【解决方案2】:

    表示外部LocalScreen 类的this 实例。

    编写不带限定符的this 将返回调用所在的inner class 的实例。

    【讨论】:

    • 还是不太明白。与“this”相比,将其编码为“LocalScreen.this”有什么区别?我测试了两者,编译器只接受“LocalScreen.this”。 aFuncCall 的第一个参数需要一个Parent 类,它是“Somethig”的父类。
    • 我也很好奇这个。您能否详细说明这意味着什么?我没有看到上面代码中定义的任何内部类;是否每个 Java 函数都有一个与其所属的类分开的关联匿名类?
    • @rascher:有内部类在使用; OP 没有将它们包含在代码 sn-p 中。此语法仅在非静态内部类中受支持。
    • 很高兴您提供了官方 Java 文档的链接。
    【解决方案3】:

    编译器获取代码并对其执行类似的操作:

    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;
    • 这是一个被低估的问题答案。有趣的东西。
    【解决方案4】:

    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”之类的东西.一个类没有任何“this”,只有实例有才能引用自己...
    【解决方案5】:

    我知道你的困惑是什么。我刚刚遇到这个问题,应该有特殊的场景来区分它们。

    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.thisthis 之间的差异

    在 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 始终指向外部 THIS 类,由 val x 引用,但 this 超出了匿名新操作的范围。

    【讨论】:

      猜你喜欢
      • 2010-11-08
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      • 2016-07-05
      • 2016-10-12
      • 1970-01-01
      • 2012-02-03
      • 2021-10-21
      相关资源
      最近更新 更多