Java 在OpenJDK和Oracle中,匿名内部类直接调用外部类实例方法有什么区别?
今天,我回顾了相同的Android代码,发现了一个奇怪的现象 它是直接称为外部类实例方法的匿名内部类 在我看来,直接调用一个方法相当于在方法前面直接添加Java 在OpenJDK和Oracle中,匿名内部类直接调用外部类实例方法有什么区别?,java,javac,openjdk,Java,Javac,Openjdk,今天,我回顾了相同的Android代码,发现了一个奇怪的现象 它是直接称为外部类实例方法的匿名内部类 在我看来,直接调用一个方法相当于在方法前面直接添加this,而this是一个内部类的实例 根据此逻辑,外部类的实例直接在匿名内部类中调用,这将导致编译错误 但实际上编译这个应用程序,并没有问题。运行日志正常 因此,编写一个简单的演示来验证前面的概念是错误的。代码显示如下: public class InnerClass { public static void main(String[]
this
,而this
是一个内部类的实例
根据此逻辑,外部类的实例直接在匿名内部类中调用,这将导致编译错误
但实际上编译这个应用程序,并没有问题。运行日志正常
因此,编写一个简单的演示来验证前面的概念是错误的。代码显示如下:
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;
}
}
在甲骨文中:在OpenJDK中:
那么,在OpenJDK和Oracle中,匿名内部类直接调用外部类实例方法有什么区别呢 在哪里可以找到文档来查看这些差异 我努力工作,但没有得到明确的答案 谢谢 附言 根据我的观点
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;
}
}
公共类内部类{
公共静态void main(字符串[]args){
新的InnerClass().process();
}
公共程序(){
新线程(){
@凌驾
公开募捐{
//根据我的观点
//toString(“测试”)
//
//此.toString(“测试”)
//“this”是Thread的实例
//我的观点有什么错误?
System.out.println(toString(“测试”));
}
}.start();
}
公共字符串到字符串(字符串){
返回字符串;
}
}
问题是
public void run() {
System.out.println(toString("test"));
}
正在匿名线程
子类上调用toString
,即Thread::toString()
。没有Thread::toString(String)
,并且不考虑封闭范围中的toString(String)
方法
JLS声明,如果内部类中没有具有所需名称的方法,它将仅检查封闭/外部类中的方法。见:
如果表单为MethodName,即仅为标识符,则:
- 如果标识符出现在可见方法声明的范围内
使用该名称(§6.3,§6.4.1),然后:
- 如果有一个封闭类型声明,该方法是该声明的一个成员,那么让T作为最内部的类型声明。班级或 搜索的接口是T 此搜索策略称为“梳规则”。在查找之前,它会在嵌套类的超类层次结构中有效地查找方法 用于封闭类及其超类层次结构中的方法。看见 §6.5.7.1为例
javac
codebase(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
所以。。。大概您应该重新运行OpenJDKJava7测试,并确保编译的源代码相同 还请注意,一个是Java 8,另一个是Java 7。@MacStevins我看到了url.,但我找不到详细信息。例如,javac句柄匿名内部类直接调用外部类的实例方法的区别为什么要比较Windows和Unix?Java 7到Java 8?在你说软件本身存在差异之前,先限制外部差异。OpenJDK和OracleJavaC之间没有这种差异(将来也不会有)。您只是在比较Java7和Java8(在不同的操作系统和地区)。
toString(String)
不是toString()
。在这两种情况下,它都是Thread#toString
我知道………嗯,为什么你说它调用Object.toString()?因为在这种情况下,名称才是最重要的。请参阅我刚才引用的JLS文本。的确,请通读全文。啊。。。。我明白你的意思。