java - 为什么从线程调用类函数在 Java 中有效?
问题描述
所以我得到了这个奇怪的场景,它工作得很好,但对它为什么工作没有任何意义。根据我在 C++ 方面的经验,我非常确定这根本行不通,并且会在编译期间引发错误。
public class Practice {
private void testFunction() {
System.out.println("working fine");
System.out.println("testFunc: " + this);
}
public void start() {
System.out.println("start: " + this);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("run: " + this);
testFunction();
}
}).start();
}
}
// Inside main
Practice practice = new Practice();
practice.start()
输出
start: com.company.Practice@5e2de80c
run: com.company.Practice$1@6720b744
working fine
testFunc: com.company.Practice@5e2de80c
为什么!?为什么这行得通?我如何testFunction()
从 Runnable 调用?我不应该创建一个新实例然后调用该函数Practice p = new Practice(); p.testFunction()
吗?Java如何知道它testFunction()
是Practice
类的一部分而不是Runnable
?
而且,为什么this
in的值与testFunction()
相同start()
?不应该是一样的run()
吗?
解决方案
您在这里有一个“内部班级”。
内部类的实例(Runnable 的匿名子类)将包含对它们创建的外部类的引用(这里是 Practice 的实例),并且可以在这些外部实例上调用方法。
你testFunction();
被编译成类似的东西this.$myOuterInstance.testFunction();
Java 怎么知道 testFunction() 是 Practice 类的一部分而不是 Runnable?
编译器通过首先查看内部类然后转到外部范围来解决这个问题,外部范围不仅包括包含类,而且还包括您在该start
方法中可能拥有的任何有效的最终局部变量。
这也类似于变量和字段的解析方式(当您有名称冲突时使用一些隐藏规则)。
还有,这个 in 的值怎么和
testFunction()
一样start()
?不应该是一样的run()
吗?
No.在(as is )testFunction
的实例上调用。Practice
start
run
在 Runnable 的实例上调用Practice$1
。
推荐阅读
- python - 如果第一个属性相同,则按多个属性对对象列表进行排序
- python - 以编程方式导入包中的所有模块
- tensorflow - 在张量流的推理过程中如何获得神经元的激活?
- arrays - 如何将指针分配给结构内的数组?
- jenkins - MsBuild 在 Jenkins 上失败
- printing - 打印过滤器管道进程已终止。错误信息:0x800706BE
- postgresql - 未打开 refcursor 时 Postgres 捕获异常
- html - Bootstrap Carousel 可切换/动态选项卡
- tensorflow - Heatmap on custom model with transfer learning
- scala - 如何在 spark scala 中处理模式匹配中的 Null