我在 java 中为特定用例使用了一个静态嵌套类。一个最小的例子如下所示:
public class Foo {
static int fooInner = getInner(); // CASE 1
private static class StaticFoo {
int fooInner = getInner(); // CASE 2
public int useFooInner(){
System.out.println(fooInner);
//do something
}
}
}
问题是案例 1 中的内存分配与案例 2 中的内存分配有何不同?还是一样?如果我也将案例 2 变量设为静态怎么办。内存使用会有所不同吗?
注意:请不要提及会发生阴影。虽然我已经将两个变量都放在那里,但这是一个“OR”案例,这就是“CASE”的原因。
PS : 感觉内存使用应该是一样的。由于嵌套类是静态的,它不会为每个对象创建,因此实例变量
fooInner
(案例 2)也将只创建一次。因此,getInner() 函数将只运行一次。但这只是抽象层面+直觉。一个更具描述性的答案将不胜感激!
最佳答案
它们是不同的。
从内存分配的角度来看,静态内部类与顶级类没有什么不同。您的 StaticFoo
将被编译成一个类 ( Foo$StaticFoo.class
),它在运行时基本上独立于其父类。在编译时,对私有(private)成员进行访问检查。
因此,在情况 1 中,您在类中有一个静态字段。它将作为 Foo.class
上的字段分配。堆上的对象。每个加载 Foo 类的 ClassLoader 将只有一个实例,这通常意味着整个 JVM 只有一个共享实例。
在情况 2 中,您在 Foo$StaticFoo
中有一个实例字段。类(class)。在堆上,将为创建的每个 StaticFoo 实例分配空间(并分配一个值)。创建的每个 StaticFoo 都将访问它自己的该字段的实例,因为它不是 final
,每个实例的值可以独立改变。
如果您更改了 StaticFoo.fooInner
成为 static
,则与案例 1 完全相同。
注:以上仅适用于 Java 8 及更高版本。对于早期的 JVM,在每种情况下分配的内存量仍然与上面的描述相匹配,但是静态变量,以及每个 ClassLoader 的单例,也存储在不同的内存池中:PermGen 空间而不是主堆。见 this answer更多细节。
关于java - 静态嵌套类的实例变量与外部类的静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68219132/