java - 静态嵌套类的实例变量与外部类的静态变量

标签 java java-8 static static-classes

我在 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/

相关文章:

Java 等同于 C# 中的 where

java - lambda 表达式在 netbeans jdk 1.8 项目中不起作用

c# - 重载 Console.ReadLine 可能吗? (或任何静态类方法)

java - HOUR_OF_DAY 日期显示 12 小时制

java - XSSFWorkbook、XSSFSheet 不起作用 - NetBeans 8.0.2

java - 如何在java中处理twilio短信状态回调

java - 将 <Object, AtomicInteger> 映射到关联数组

java - 我应该为我的主程序变量使用静态变量吗?

java - 如果另一个类中的方法不是静态的,为什么我无法获取该方法的返回值?

java - 如何处理数组 :Exception in thread "main" java. lang.ArrayIndexOutOfBoundsException: 3