Java中的"this"关键字:它是如何工作的?

8

我知道在Java中,“this”作为引用。我们只能在类成员内部使用它。

我的问题是... 因为它用于类的成员,这意味着它必须是实例变量或参数之一。

假设它是方法的参数,但它在块中起作用。块不包含任何参数..你能解释一下它是什么吗?在Java中它是如何定义的?JVM如何使用它?


2
你的问题毫无意义。关于参数和块工作是什么意思? - polygenelubricants
我试图翻译这个,我已经编辑到最后一段了。也许有人能够理解并尝试翻译它。 - Kieren Johnstone
你能给出代码示例吗? - josefx
7个回答

32
从语言学角度来看,this既不是局部变量也不是参数。从句法上讲,它是一个关键字。从语义上讲,它是一种显式地表示“当前对象”的方式;参见JLS 15.8.3。例如:
  • this.<attributeName> 明确引用当前对象的实例级属性。
  • <methodName>(this)调用一个方法,并将对当前对象的引用作为显式参数传递。

this关键字在Java中有其他用途,不完全意味着“当前对象”:

  • this(<optArgumentList>)作为构造函数中的第一条语句链接到同一类中的另一个构造函数;JLS 8.8.7
  • <className>.this在内部类中引用当前对象的封闭类的实例;JLS 15.8.4

从实现的角度来看,“this”引用可以看作是在每次调用实例方法时传递的一个隐藏或隐含参数。事实上,这就是虚拟机中的“invoke*”字节码如何处理对象引用的方式。你需要将目标对象引用推入“opstack”,然后跟着每个参数值,最后执行“invoke…”指令。(详见此处。)

3
@polygenelubricants - 我借用了你的参考资料。谢谢。 - Stephen C
虽然这个答案是正确的,但你也可以考虑看一下这里的另一个评论https://dev59.com/l0_Ta4cB1Zd3GeqPB5A8#3413324,那里有一个更"轻量级"的答案。 - alexsmail
@alexsmail - 是的,这是一个更简单的答案。但这种简单性来自于说一些从语言学角度来说并不严格有意义的事情。它假设了一个特定的实现模型。如果读者能够理解计算机在指令级别上的工作方式,那么它才是简单的。 - Stephen C
@alexsmail,如果你想要更加技术化,大多数实现会在x86上将“this”保留在ECX/RCX寄存器中,避免将其放入堆栈中(当代码被编译而不是解释时)。 - bestsss

7

实例方法在实际实例、实际对象的上下文中被调用。

class 的实例方法中,this(在大多数情况下)指的是这个对象。这是一个相对的引用:当同一个方法在另一个对象上调用时,在该方法执行期间,this 现在指的是第二个对象。

为了完整起见,应该提到 Java 还有所谓 "qualified" this,它可以用来引用内部 classenclosing 对象,而不是调用该方法的对象。

在构造函数中它还可以出现,但有一些限制,它可以调用同一类的另一个构造函数。super 也可以这样使用。

参考资料

  • JLS 15.8.3 this
    • 当用作主表达式时,关键字 this 表示一个值,该值是对调用实例方法的对象或正在构造的对象的引用。
  • JLS 15.8.4 Qualified this
    • 任何词法封装的实例都可以通过显式限定关键字 this 来引用。
  • JLS 8.8.7.1 显式构造函数调用
    • 替代构造函数调用 以关键字 this(可能带有显式的类型参数前缀)开头。它们用于调用同一类的替代构造函数。

6
在Java中,this被定义为一个关键字,因此不是普通的变量名称,具有特殊行为。Java语言规范中定义了this的行为,例如:当作为主要表达式使用时,关键字this表示一个值,即对调用实例方法(§15.12)或正在构造的对象的引用。 第15.8.3节

5
每次您调用非静态方法时,“this”将被隐式地作为参数传递。您可以将其视为语法糖,但在机器级别上,它确实是一个额外的参数被传递。
class Person
{
  string name;
  int age;
  void print(){ System.out.writeln(name+" "+age); }
}

以下是类似于伪代码的工作方式:

class Person
{
  string name;
  int age;
}

void print(Person this)
{
  System.out.writeln(this.name+" "+this.age);
}

2

一种思考方式是将其视为实例方法和构造函数的隐式参数。在构造函数的情况下,构造函数的工作是设置“this”,而在实例方法的情况下,它们可以根据需要操作“this”。

请注意,Java还具有一些语法糖,允许您隐含地引用“this”的字段和方法,而无需指定this.foo


1

this 将会给你一个对实际实例的引用。在构造函数中非常常见,例如:

class Dog {
   String name;

   public Dog(String name) {
      this.name = name;
   }
}

构造函数的主要目的是避免影子变量。在您的示例中,编译器不知道哪个变量名为 name,因此 this.name 是实例变量,而 name 是构造函数中的参数。 - Truong Ha

0

你可以把'this'想象成指代自己。就像我一样,[attribute]可以访问自身的属性或方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接