问题描述
我对Java中的匿名对象有疑问。
如果我创建一个具有一个匿名对象的静态方法(name = go()
),并且该匿名对象使用go()
的局部变量。
我知道用于匿名对象的局部变量必须声明为final
。
然后在堆栈区域而不是堆区域中创建final variable(numberCnt)
。
堆栈区域不是GC的目标。
如果我无限地调用go()
,是否会发生堆栈溢出?
以下是我的问题来源。
package com;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestMain {
public static void main(String[] args) {
int i =0;
while(true) {
i++;
go(i);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if(i > 10_000_000) {
i=0;
}
}
}
private static void go(int i) {
int numberCnt = i;
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
String rtnValue = "Number=>" + numberCnt;
System.out.println("Number=>" + rtnValue);
return rtnValue;
};
};
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(callable);
}
}
解决方法
匿名类复制在创建匿名类对象时捕获的变量的值。因此,基本上,您的匿名类具有一个用于捕获int
的隐藏numberCnt
实例变量,并且您可以想象,在后台,编译器基本上将numberCnt
传递给隐藏的“构造函数”您的匿名类来初始化此隐藏的实例变量。函数返回时,go
的堆栈帧消失了,并且堆栈上go
的堆栈帧不超过1个。您只会在堆上得到很多匿名类的实例,并且每个实例都有一个int
实例变量,其值不同。