匿名内部类有什么区别直接调用OpenJDK和Oracle中的外部类实例方法?

时间:2017-12-09 03:36:56

标签: java javac openjdk

今天,我查看了相同的Android代码,发现了一个奇怪的现象。

它是直接称为外部类实例方法的匿名内部类。

在我看来,直接调用方法相当于在方法之前直接添加thisthis是内部类的实例。

根据这个逻辑,在匿名内部类中直接调用外部类的实例,这将导致编译错误。

但实际上编译这个应用程序,没问题。运行日志正常。

因此,编写一个简单的Demo来验证以前的概念是错误的。代码如下所示:

public class InnerClass {
    public static void main(String[] args) {
        new InnerClass().process();
    }

    public void process() {
        new Thread() {
            @Override
            public void run() {
                System.out.println(toString("test"));
            }
        }.start();
    }

    public String toString(String string) {
        return string;
    }
}

在Oracle中:
enter image description here

在OpenJDK中:
enter image description here

那么,匿名内部类有什么区别直接调用OpenJDK和Oracle中的外部类实例方法?

我在哪里可以找到文档来查看这些差异?

我努力工作,但没有得到明确的答案。

感谢。

P.S。

根据我的观点

public class InnerClass {
    public static void main(String[] args) {
        new InnerClass().process();
    }

    public void process() {
        new Thread() {
            @Override
            public void run() {
                // In According to my point of view
                // toString("test")
                // <==>
                // this.toString("test")
                // and `this` is the instance of Thread
                // what's the error of my view?
                System.out.println(toString("test"));
            }
        }.start();
    }

    public String toString(String string) {
        return string;
    }
}

image

1 个答案:

答案 0 :(得分:1)

问题在于

        public void run() {
            System.out.println(toString("test"));
        }

在匿名toString子类上调用Thread,即Thread::toString()。没有Thread::toString(String),并且不考虑封闭范围中的toString(String)方法。

JLS声明如果在内部类中没有具有所需名称的方法,它将仅检查方法的封闭/外部类。见JLS 15.12.1

  

如果表单是MethodName,即只是一个标识符,那么:

     
      
  • 如果标识符出现在可见方法声明的范围内   使用该名称(§6.3,§6.4.1),然后:

         
        
    • 如果存在该方法为成员的封闭类型声明,则让T为最内层的类型声明。班级或   搜索界面是T。

           

      此搜索政策称为“梳理规则”。它在查找之前有效地在嵌套类的超类层次结构中查找方法   用于封闭类及其超类层次结构中的方法。看到   §6.5.7.1为例。

    •   
  •   

至于为什么OpenJDK Java 7接受你的测试类....如果确实如此,我称之为编译器错误。但它将是一个普通的Java 7错误,而不是OpenJDK特有的错误。对于同一版本的Oracle和OpenJDK版本,javac代码库(AFAIK)完全相同。

有趣的是,我有一份Oracle Java 6,该版本的javac也称此为编译错误。

$ /usr/java/jdk1.6.0_45/bin/javac InnerClass.java 
InnerClass.java:10: cannot find symbol
symbol: method toString(java.lang.String)
                System.out.println(toString("test"));
                                   ^
1 error

所以......也许......你应该重新运行你的OpenJDK Java 7测试,并确保你正在编译相同的源代码!