Java this关键字底层逻辑和三大关键用法
Java this关键字底层逻辑和三大关键用法
一、底层核心结论
- this 本质就是:对象在堆内存中的内存地址引用。
- 每个 Java 对象,天生自带一个隐藏的 this 引用,指向自己堆内存地址。
- 调用成员方法时,JVM 默认偷偷把当前对象地址传给方法,方法里的 this 就是这个地址。
this.xxx本质:通过对象内存地址,找到堆里的成员变量/方法。
二、内存底层视角:对象是怎么存的
1. 对象内存分布
创建对象 Student s = new Student();
- 栈内存:存引用变量
s,保存堆内存地址 - 堆内存:存真实对象
- 成员变量(属性)
- 隐藏的 this 指针(天生自带,看不见但真实存在)
通俗理解:
每个对象出生时,自带一张自己的身份证地址,这张身份证就是 this。
2. 方法调用底层原理(关键)
当执行:
s.setName("张三");
JVM 底层做了3件事:
- 拿到栈中
s保存的堆对象地址 - 隐式把这个地址传给 setName 方法,作为隐藏第一个参数
- 方法内部的
this,就接收了这个对象地址
相当于底层真实执行是这样(假设的代码):
// JVM 偷偷帮你加的隐藏参数
public void setName(Student this, String name){
//this隐藏在了参数列表中的第一个位置!!!
this.name = name;
}
this在更加底层的代码中会显示在参数列表中的第一个位置,所以我们每次参数列表中输入了n个参数,但实际上底层代码中有n+1个参数,就是有this存在。
这也就是为什么方法里能直接用 this:JVM 自动传了对象地址进来。
Java this关键字三大用法
一、this.属性名 用法
大部分时候,普通方法访问类的成员变量时,无须使用 this 前缀。
但如果方法局部变量、方法参数 和 类的成员变量同名,发生了变量名覆盖,程序又想访问类本身的成员变量,就必须加上 this 前缀区分。
示例:学生类 Student 定义
public class Student {
// 成员变量:姓名、年龄、分数
private String name;
private int age;
private double score;
}
上面 name、age、score 被 private 修饰,类外部不能直接赋值访问。
我们可以给 Student 类添加有参构造方法,通过传参给成员变量赋值。
// 构造方法:给学生三个属性赋初始值
public Student(String name, int age, double score) {
this.name = name; // 给当前对象的姓名赋值
this.age = age; // 给当前对象的年龄赋值
this.score = score; // 给当前对象的分数赋值
}
构造方法里的 this 代表当前正在创建的学生对象。
- 等号左边
this.name:当前学生对象身上的成员变量 name - 等号右边
name:构造方法括号里传进来的参数
测试 main 方法
public static void main(String[] args) {
Student stu = new Student("李四", 20, 95.5);
System.out.println("学生信息如下:");
System.out.println("学生姓名:" + stu.name +"\n学生年龄:" + stu.age +"\n考试分数:" + stu.score);
运行结果
学生信息如下:
学生姓名:李四
学生年龄:20
考试分数:95.5
提示:当类的成员变量名和方法/构造的参数名相同时,必须用 this.属性名 指明访问的是类的成员变量,避免被局部变量覆盖。
二、this.方法名 用法
this 最大作用之一:类中的一个普通方法,调用本类里另一个普通方法。
场景举例
定义学生类 Student,学生有 study() 学习方法、read() 读书方法;
要求:学习的时候,先要执行读书方法。
第一种写法(不推荐,重复创建对象)
public class Student {
// 读书方法
public void read() {
System.out.println("正在认真读书");
}
// 学习方法,需要依赖读书方法
public void study() {
// 额外新建一个学生对象来调用read()
Student s = new Student();
s.read();
System.out.println("正在专心学习");
}
}
测试代码:
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();
stu.study();
}
}
这种写法会产生两个 Student 对象:
- main 方法里创建的 stu 对象
- study 方法内部又 new 了一个新 Student 对象
首先我们得知道,没有 static 修饰的普通方法,必须由对象调用,即非静态方法调用,必须通过对象调用。
那么问题来了,有没有必要重新 new 一个新学生对象?
完全没必要啊
调用 study() 方法时,已经存在一个学生对象了,直接用当前这个对象就行,不用额外新建。
而 this 就可以代表当前调用方法的对象。
第二种写法(推荐:用 this.方法名)
public class Student {
public void read() {
System.out.println("正在认真读书");
}
public void study() {
// this 代表当前学生对象,调用自己的read方法
this.read();
System.out.println("正在专心学习");
}
}
谁调用 study(),this 就代表谁:
stu.study()调用时,this 就指向 stu 这个学生对象。
简写形式(开发常用)
同一个类中,普通方法互相调用 可以省略 this,底层依然隐含 this:
public void study() {
read(); // 省略this,等价于 this.read();
System.out.println("正在专心学习");
}
注意:static 静态方法不能使用 this。
因为静态方法属于类,不属于某个具体对象,而 this 必须指向某一个实例对象,所以静态方法里禁止用 this,也不能直接访问非静态方法。
总之,方法里访问本类其他普通方法、成员变量,加不加 this 效果一样;
只是省略 this 是语法简写,底层依然隐含 this 引用。
三、this() 访问本类构造方法
this() 专门用来调用本类中其他构造方法:
- 空括号
this():调用无参构造 - 带参数
this(参数):调用有参构造
语法硬性规则:
- 一个构造方法里,只能写 1 次
this(...) this()只能写在构造方法第一行- 只能在构造方法中使用
- 不能循环互相调用
示例代码
public class Student {
String name;
// 无参构造
public Student() {
// 调用本类带一个字符串参数的有参构造
this("张三");
}
// 有参构造
public Student(String name) {
this.name = name;
}
// 打印学生姓名
public void printInfo() {
System.out.println("姓名:" + name);
}
public static void main(String[] args) {
// 调用无参构造
Student stu = new Student();
stu.printInfo();
}
}
运行结果
姓名:张三
逻辑解释
- 执行
new Student(),先走无参构造方法; - 无参构造第一行
this("张三"),跳转调用有参构造; - 有参构造中
this.name = name,给当前学生对象的 name 赋值为 “张三”; - 有参构造执行完毕,回到无参构造,构造流程结束;
- 调用
printInfo()打印姓名。
全程只创建一个学生对象,this() 只是在同一个对象初始化过程中,复用另一个构造方法的代码,不会重复 new 对象。
更多推荐


所有评论(0)