繁体   English   中英

静态方法和字段是否在定义它们的类的实例中占用内存?

[英]Do Static Methods and Fields take up memory in an instance of the class they are defined in?

例如,如果我要创建以下类:

public Class ExampleClass {
  
  private static String field1;
  private String field2;

  public ExampleClass(String field2) {
    this.field2 = field2;
  }

  public static staticMethodExample(String field1) {
    this.field1 = field1;
  }
}

如果我要创建ExampleClass的实例。 该实例是否包含我创建的静态方法和/或字段的代码?

我有一个对象将代表我数据库中一行的一些数据。 我想从数据库中的每一行创建这些对象的列表。 数据库有数千行。 我正在创建的静态方法将在将数据库中的值放入对象构造函数之前对其进行格式化。

我不想通过将方法存储在对象的每个实例中来膨胀代码。 因此,如果静态方法确实在对象的每个实例中都占用了空间,那么我宁愿创建一个名称为ExampleClassBuilder的单独类。 并将格式化静态方法放在那里。

不,静态方法和字段在类的实例中不占用空间。

你在这里制造了一些混乱。 编译程序时,每个方法(静态或非静态)的代码都“存储”在已编译的程序中(在 Java 的情况下,在.class文件中)。 当您执行一个程序时,静态成员- “属于”一个类,如您问题中的field1 - 为您的整个程序分配一次。 其他“普通”类成员 - 如您问题中的field2 - 为您创建的每个新实例分配。

当你创建一个对象的新实例时,它的各种方法的代码没有被“分配”,因为它已经以编译形式存在于你的程序中。

此类实例的堆上的数据大致如下*:

size (bytes) | description
--------------------------
8            | A pointer to the singleton object representing ExampleClass
8            | A pointer to the value stored in field2

就是这样。 不存储静态字段。 没有一个方法是,甚至不是实例方法! 这只是非静态字段。 那个指向单例的指针? 只有一种数据结构代表了整个 VM 的 ExampleClass。 有 1000 个 ExampleClass 实例? 仍然只有一个。

这些大小可以更小,具体取决于 VM 配置。

那么 java 怎么知道 ExampleClass 的实例有一个名为instanceMethod的方法呢? 通过跟踪指向描述 ExampleClass 本身的数据结构的指针,并注意到它具有该结构。 这个:

class Foo {
    public void hello() {}
}

基本上是语法糖:

class Foo {
    public static void hello(Foo receiver) {}
}

但请注意,实例方法执行动态分派,而静态方法则不然。 这应该可以解释为什么方法(甚至实例方法)不占用每个实例的任何“内存”。 整个班级只有一次。 同样的技巧不能应用于实例字段。

*) 这过于简单化了,JLS 或 JVMS 都没有指定,但它反映了几乎所有流行的 VM 的实际作用。

静态变量和方法不会增加 Object 实例的大小。 这些字段和方法实际上是添加到 Class 对象中的。

否:当我们创建静态变量或方法时,它存储在堆上的特殊区域:元空间(对于 Java 8 和Permgen对于旧版本)。

每当一个类被加载static变量以及方法被加载到内存中时,允许任何实例(不鼓励)或直接使用它们。 因此,任何对象都可以更改变量的值,但也可以在不创建类的实例的情况下对其进行操作。 在此处查看更多https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM