【问题标题】:In a Java class, do we have separate copies of instance methods for each object of that class?在 Java 类中,对于该类的每个对象,我们是否有单独的实例方法副本?
【发布时间】:2018-02-13 17:26:21
【问题描述】:

如果不是,那么在运行时,实例方法究竟如何使用同一个对象的实例变量? 例如我有一个class A,有实例变量aVariable 和非静态方法aMethod()。现在我有一个A 类 的对象,我们将它命名为aObject。 aMethod 使用 aVariable。当我调用这个方法时,它如何知道在内存中使用哪个aVariable,以及它存储在哪里?我们是否将所有对象信息传递给方法? 请帮我解决这个问题。

【问题讨论】:

标签: java


【解决方案1】:

它使用类的特定实例的实例方法:

public class Person{
  private String name;
  public Person(String name){
    this.name = name;
  }

  public void printName(){
    System.out.println(name);
    System.out.println(this.name);
  }
}

这里printName 使用name 变量。假设我们有两个 Person 实例

Person a = new Person("Andrew");
Person b = new Person("Bert");

当您在这些实例中的一个(y)上调用实例成员时,该实例不知道除自身之外的任何其他实例,因此,如果您调用 a.printName(),它将始终打印 Andrew,因为这是存储在a 变量,如果你调用 b.printName() 它总是会打印 Bert。

如您所见,添加this. 不会改变printName 方法中的任何内容,仅在有歧义时才需要,因为存在同名的局部变量。

但它总是会从当前实例中获取值。

【讨论】:

    【解决方案2】:

    首先,您应该了解在创建对象的新实例时内存是如何工作的。总而言之,当你创建一个对象的新实例时,它会在内存中腾出空间来为实例分配整个堆栈中的所有变量。在互联网上很容易找到它的确切工作原理,但这只是一个基本的解释。

    不过,重要的是要知道还有其他变量不能以这种方式工作。例如,静态变量存在,其行为方式是,如果您更改此变量的值,它将在对象的所有实例中发生变化。

    但一般来说,你必须想象一堆将创建实例的对象变量,以及将创建最终程序的这些实例的堆栈

    【讨论】:

      【解决方案3】:

      参考JVM Spec, Sec 3.7

      int add12and13() {
          return addTwo(12, 13);
        }
      

      这编译为:

      Method int add12and13()
      0   aload_0             // Push local variable 0 (this)
      1   bipush 12           // Push int constant 12
      3   bipush 13           // Push int constant 13
      5   invokevirtual #4    // Method Example.addtwo(II)I
      8   ireturn             // Return int on top of operand stack;
                              // it is the int result of addTwo()
      

      通过首先将当前实例 this 的引用压入操作数堆栈来设置调用。然后推送方法调用的参数,int 值 12 和 13。

      因此,this 引用(或接收器参数的任何其他值)只是作为另一个参数推入堆栈。因此,每个实例不需要单独的方法副本。

      【讨论】:

        【解决方案4】:

        不,我们没有单独的实例方法副本。 这样做的方法是传递对this 的隐含引用:

        对于一个方法

        public void doSomething(Object param);
        

        ,调用

        this.doSomething(myParameter);
        

        解析为

        doSomething(this, myParameter);
        

        【讨论】:

          【解决方案5】:

          当您创建一个对象“aObject”并使用 aObject.aMethod() 调用该方法时,您使用“aObject”,这是您指定要在哪个实例上调用该方法的地方!

          显然,当您创建多个实例时,您会创建多个内存分配,它们位于不同的位置。

          实例变量只是一个链接或指针,指向存储该实例所有相关数据的内存位置。

          【讨论】:

            猜你喜欢
            • 2020-09-18
            • 1970-01-01
            • 1970-01-01
            • 2020-04-21
            • 1970-01-01
            • 2020-09-20
            • 2015-11-17
            • 1970-01-01
            • 2012-08-14
            相关资源
            最近更新 更多