Java中的“this”变量实际上如何设置为当前对象?

2022-09-01 11:33:33

考虑:

class TestParent{
  public int i = 100;
  public void printName(){
    System.err.println(this); //{TestChild@428} according to the Debugger.
    System.err.println(this.i); //this.i is 100.
  }
}

class TestChild extends TestParent{
  public int i = 200;
}

public class ThisTest {
  public static void main(String[] args) {
    new TestChild().printName();
  }
}

我知道有人问过类似的问题,但我无法对Java中的“this”变量有一个确切的理解。

让我试着解释一下我如何理解上图的结果。

  1. 由于它是调用该方法的对象,因此根据调试器,第 6 行中的变量设置为对象 - {TestChild@428}。new TestChild()printName()thisTestChild

  2. 但是,由于Java没有虚拟字段 - 我不完全确定这意味着什么,但我从概念上理解它是支持多态性的Java方法相反的 - 在编译时设置为100。this.iTestParent

  3. 因此,无论是什么,在方法中将始终是类中的变量。thisthis.iTestParentiTestParent

我不确定我的理解是否正确,所以如果我错了,请纠正我。

而且,我的主要问题是,

如何将变量设置为调用该方法的当前对象?它是如何实际实施的?this


答案 1

从本质上讲,两者之间没有区别

this.foo()

anyObject.foo()

因为两者都以相同的方式“实现”。请记住,“最终”“面向对象只是一个抽象,而在”现实“中发生的事情是这样的:

foo(callingObject)

换句话说:每当你使用一些对象引用来调用一个方法时......最后,对某个对象没有调用。因为在汇编程序和机器代码的深处,像“对某物的调用”这样的东西并不存在。

真正发生的事情是对函数的调用;第一个(在源代码级别上隐式/不可见)参数是该对象。

顺便说一句:你实际上可以用Java写下来,比如:

class Bar {
   void foo(Bar this) { ... }

和以后使用

new Bar().foo();

对于this.fieldA,最后:你有一个对内存中某个位置的引用;和一个表,告诉您将在哪个“偏移量”上找到字段A。

编辑 - 仅用于记录。如果你对foo(Bar this)的更多细节感兴趣 - 你可以转向这个问题;在它背后的Java规范中给出细节!


答案 2

这里发生的事情是,有两个完全不同的字段,它们都被称为;要使用他们的全名,一个是,一个是 。iTestParent::iTestChild::i

因为该方法在 中定义,当它引用时,它只能看到,它被设置为100。printNameTestParentiTestParent::i

而当您在 中设置为 200 时,调用的两个字段都是可见的,但是由于它们具有相同的名称,因此隐藏 ,并且您最终会设置并保持不变。iTestChildiTestChild::iTestParent::iTestChild::iTestParent::i