作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个函数 multi2
,它将内部类 Inner
作为 Object
返回。
a
会发生什么情况 - 它保存在哪里以及如何访问它?
public class C {
private static Object multi2(final int a) {
class Inner {
public int hashCode() {
return 2*a;
}
}
return new Inner(); // What happens to a?
// Who allocates a?
// Can I Access a?
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
}
}
最佳答案
在实现级别发生的事情是 a
的值的副本保存在 合成实例变量 中,该变量在 C 的编译版本中声明.Inner
类。
a
的值通过一个额外的参数传递给编译后的Inner
构造函数。
C.Inner.hashCode
方法使用合成变量的值。访问Inner.hashCode
源码中的a
,转化为访问编译后代码中对应的合成变量。
外部作用域中的变量必须是final
1。 Inner
类中的合成变量必须是 final
2。这维持了这样一种错觉,即(可能)Inner
类的多个实例看到相同的 a
变量。 (它们不是,但由于无法更改变量,因此内部类的代码无法区分差异。)
如果您使用 javap
查看编译示例的字节码,您将看到用于在外部类和内部类中实现它的机制。
1 - 或者从 Java 8 开始有效的 final。
2 - 如果 a
可以被 Inner
方法改变,那么两个具有相同外部类的 Inner
实例需要共享一个可变变量,其生命周期(现在)长于 multi2
调用的堆栈帧。这需要以某种方式将 a
从堆栈变量转换为堆上的东西。这将既昂贵又复杂。
关于java - 函数对象内部类中的变量/对象会怎样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51135078/
我是一名优秀的程序员,十分优秀!