【问题标题】:In Java where do the static methods go during the creation of an object in java?在Java中,在Java中创建对象期间静态方法去哪里了?
【发布时间】:2017-12-08 22:54:42
【问题描述】:

如果有一个类有一些方法,那么每当我们创建一个新对象时,该对象就会在堆上创建,并带有字段和方法。如果我们有一个具有静态和普通方法的类,并且我们创建了这个类的一个对象,实例变量和普通方法仍然存在,但是静态方法是如何创建的呢?

【问题讨论】:

  • 您需要重新审视您的第一个假设:object 根本不包含方法。它不是对象状态的一部分。
  • 那么既然我们调用了方法,那么方法代码在哪里。是否有两个空间称为程序空间和数据空间。当我们调用方法时,实例变量会从数据空间复制到寄存器,程序计数器从程序空间指向方法的开始地址。
  • 每个对象都有说明其实际类型的信息,JVM 将其与方法相关联。但是,必须用与所有其他相同类型的对象相同的信息来填充一个对象,这将是没有意义的并且真的浪费。 (想想java.lang.String 中的所有方法——你真的希望每个字符串对象分别包含每个方法的某些表示的副本吗?)

标签: java heap-memory static-methods


【解决方案1】:

所有方法,无论是静态的还是非静态的,都是的一部分,并且类存储在非堆内存中。

所有驻留在堆中的结构包含:

  • 指向该对象作为实例的类的指针
  • 每个非静态字段的当前值(对象字段的引用、原始字段的值)

例如:

 public class Person {
     private String name;
     private int age;

     public String getName() {
         return name;
     }

     // ... etc.
 }

非堆内存中的一个结构包含:

  • 关于类的元数据,例如它的名字Person,一个指向它的超类的指针等等。
  • getName() 和任何其他方法的字节码
  • 字节码的 JIT 优化版本

对于Person 的每个实例,我们进入堆:

  • 对类条目的引用
  • age 的 int 值
  • String 对象name 的引用

因此,至少在概念上,您可以看到运行时处理对aPerson.getName() 的调用:

  • 查看堆中对象的记录
  • 遵循对其类的引用
  • 在类中,找到方法getName()
  • 运行方法,使用对象在堆中的记录作为字段

这意味着,如果您有 1000 个 Person 实例,您仍然只有一份来自该类的代码副本,这是完美的,因为它不会从一个实例更改为下一个实例。

如果DoctorNursePatient都是Person的子类,并且如果它们都没有覆盖getName(),那么getName()的代码在内存中仍然只存在一次。 (概念上)当您调用 aNurse.getName() 时,运行时将在 Nurse 中查找 getName(),如果找到,则运行它,否则在超类 Person 中查找,找到并运行它。


我已经说过几次“概念上”了。实际上,我所描述的一些动态发生的事情可能在编译时静态发生。就理解对内存和性能的影响而言,这并不重要。

【讨论】:

    猜你喜欢
    • 2014-02-02
    • 2018-02-27
    • 2012-04-26
    • 1970-01-01
    • 2012-01-13
    • 2017-11-30
    • 2021-01-16
    • 1970-01-01
    相关资源
    最近更新 更多