Java—方法如何知道哪个对象;这";指什么?

Java—方法如何知道哪个对象;这";指什么?,java,jvm,runtime,Java,Jvm,Runtime,假设我们有一节课 public class ThisTest { String username; ThisTest(String s) { this.username = s; } public void sayHello() { System.out.println("Hello " + this.username); } public static void main(String args[]) {

假设我们有一节课

public class ThisTest {
    String username;

    ThisTest(String s) {
        this.username = s;
    }

    public void sayHello() {
        System.out.println("Hello " + this.username);
    }

    public static void main(String args[]) {
        ThisTest a = new ThisTest("Jack");

        ThisTest b = new ThisTest("George");

        a.sayHello();
        b.sayHello();
    }
}
产出(如预期):

我的问题是:在sayHello方法中,运行时如何确定堆“this”所指的对象实例

编译时,方法调用是否传递了对调用对象(a或b)的隐藏引用,然后使用“this”关键字访问该对象这就是C++所做的。 或者,“this”是在构建对象时创建的堆上对象的隐藏实例变量吗

或者,sayHello方法是否有其他机制知道“this”指的是哪个对象


本质上,如何在Java编译器级别实现“this”。

从Java编程语言的角度来看,没有强制实现,因为即使编译为Java字节码也被视为“正常”,但不是必需的

Java编程语言通常编译为字节码指令集和Java虚拟机规范(JavaSE8版)中定义的二进制格式

要了解在为Java虚拟机编译时如何实现
引用,我们必须参考以下内容:

2.6.1. 局部变量 每个帧(§2.6)包含一个称为局部变量的变量数组。帧的局部变量数组的长度在编译时确定,并以类或接口的二进制表示形式提供,以及与帧关联的方法的代码(§4.7.3)。

局部变量通过索引处理。第一个局部变量的索引为零。[…]

Java虚拟机使用局部变量在方法调用时传递参数。在类方法调用时,所有参数都以连续的局部变量的形式传递,从局部变量0开始。在调用实例方法时,始终使用局部变量0传递对正在调用实例方法的对象的引用(
this
,在Java编程语言中)。从局部变量1开始,任何参数随后都在连续的局部变量中传递


换句话说,在Java字节码中,
这个
像一个局部变量(索引为零)一样编译,在输入方法时,它用对象引用预先初始化。可以使用用于访问参数变量或显式声明的局部变量的相同字节码指令访问它。

您是否尝试过:“在编译时,方法调用是否传递了对调用对象(a或b)的隐藏引用,然后使用“this”关键字访问该对象?”这就是答案。每个方法都有隐藏的第一个参数。您还可以显式地将方法声明为
yourMethod(YourClass this,[rest of parameters]),并通过
foo调用它。yourMethod(rest或arguments)`和
this
将与
foo
(调用该方法时)具有相同的引用。thiskey javadoc没有回答我的问题,John dh它是如何在什么级别实现的?记住,(通常)有一个JVM,其中对象是第一类的。不必重复,但相关:
Hello Jack 

Hello George