1. Introduction

When you first started learning Java, you must have encountered this keyword, especially in constructor assignment, as shown in the following example:

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

	public Person(String name, int age) {
		// We must add this keyword, otherwise we cannot complete the assignment
		this.name = name;
		this.age = age; }}Copy the code

In the constructor, if the name of the member variable is the same as the name of the argument, you must add this keyword, otherwise you just assign the name of the argument to itself, not to person. name, because the local variable takes precedence over the member variable. Once the this keyword is added, since this refers to the current instance, the object’s member variable assignment can be completed.

So why is the current object accessible through the this keyword?

2. The stack frame

To understand this, first understand the stack frame structure of the JVM’s method stack as it executes methods.

The Java Virtual Machine uses methods as its most basic run unit, and the stack frame is the data structure behind the JVM’s method calls. It is also a stack element in the JVM’s run time data area, the Virtual machine stack.

Simply put, the execution of a method can be thought of as a stack frame from the stack to the stack.

The stack frame stores the method’s local variable table, operand stack, dynamic link, and method return address.When usingjavacAfter the program compiles the source Code into bytecode, the size of the local variable table required for a method stack frame and the depth of the operand stack are calculated and written to the method table’s [Code] property, regardless of the runtime of the program.

In other words, the number of local variables a method has is determined at compile time and does not change as the program runs. The [this] problem we’re going to explore today is in the local variable table of the method stack.

3. The analysis

Most persuasively, we still use the javap command to parse the compiled Class file.

public class Person {

	public void say(a) {}public static void staticSay(a) {}}Copy the code

In the previous code, there is an instance method and a static method, respectively. We already know that [this] is not accessible in the static method, but it is in the instance method.

Javac Person. Java: javap-verbose Person. Javac Person: javap-verbose Person.

public void say(a);
descriptor: ()V
flags: ACC_PUBLIC
Code:
  stack=0, locals=1, args_size=1
	 0: return
  LineNumberTable:
	line 8: 0

public static void staticSay(a);
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=0, locals=0, args_size=0
	 0: return
  LineNumberTable:
	line 12: 0
Copy the code

Focus on the Code column. Say () has a local variable with one parameter. StaticSay () has no local variables and no arguments.

Are you confused? The parameter of the say() method is empty. The body of the say() method is empty. Why does it compile to show that it has a local variable and a parameter?

In fact, for instance methods, there is at least one parameter and one local variable, which is the current object. When the JVM calls an instance method on an object, it passes a reference to the object itself as the 0th argument, so you can access the object itself using the this keyword, which is really just the 0th argument.

As follows, these two methods are actually equivalent.

public void say(Person this, String text) {
    System.out.println(text);
}

public void say(String text) {
    System.out.println(text);
}
Copy the code

4. To summarize

When the Java virtual Machine executes a method, it packages the method into a stack frame. The stack frame contains the local variable table, and the parameters are part of the local variable table. The size of a method’s local variable table is determined at compile time and does not change as the program runs. For instance methods, a hidden 0 parameter is automatically added at compile time, which is the current class. When invoking an instance method on an object, the JVM automatically passes the object reference as argument 0, and accessing [this] is actually accessing argument 0.