📖 this 关键字概述
什么是 this?
this 是一个指向当前对象的引用变量,在实例方法和构造器中使用。
this 的核心作用
- 指向当前对象实例
- 解决变量名冲突
- 在构造器中调用其他构造器
- 作为参数传递当前对象
🎯 this 的四种用法
用法1:引用当前对象的成员变量(最常见)
解决局部变量与成员变量同名问题
java
public class Student {
private String name; // 成员变量
private int age; // 成员变量
// 构造器参数与成员变量同名
public Student(String name, int age) {
// 使用this区分成员变量和局部变量
this.name = name; // this.name 是成员变量,name是参数
this.age = age; // this.age 是成员变量,age是参数
}
public void setName(String name) {
this.name = name; // 区分成员变量和参数
}
public void setAge(int age) {
this.age = age;
}
// 没有歧义时,this可以省略
public void display() {
// 这里没有局部变量name和age,可以直接访问成员变量
System.out.println("姓名: " + name + ", 年龄: " + age);
// 使用this也可以(但没必要)
System.out.println("姓名: " + this.name + ", 年龄: " + this.age);
}
public static void main(String[] args) {
Student stu = new Student("张三", 20);
stu.display();
}
}
更复杂的例子
java
public class Employee {
private int id;
private String name;
private double salary;
public void updateEmployee(int id, String name, double salary) {
// 使用this明确区分
this.id = id; // 左边是成员变量,右边是参数
this.name = name; // 左边是成员变量,右边是参数
this.salary = salary; // 左边是成员变量,右边是参数
}
public void printInfo() {
// 没有局部变量冲突,可以不用this(但用this更清晰)
System.out.println("ID: " + this.id);
System.out.println("姓名: " + this.name);
System.out.println("薪资: " + this.salary);
}
}
用法2:在构造器中调用其他构造器(this())
java
public class Rectangle {
private int width;
private int height;
private String color;
// 构造器1:默认构造器
public Rectangle() {
// 调用三参构造器,提供默认值
this(10, 10, "黑色");
System.out.println("调用默认构造器");
}
// 构造器2:只有宽高
public Rectangle(int width, int height) {
// 调用三参构造器,使用默认颜色
this(width, height, "黑色");
System.out.println("调用双参构造器");
}
// 构造器3:完整参数(主要构造器)
public Rectangle(int width, int height, String color) {
this.width = width;
this.height = height;
this.color = color;
System.out.println("调用三参构造器");
}
// 错误示例:不能形成循环调用
/*
public Rectangle() {
this(10, 10); // 调用双参构造器
}
public Rectangle(int width, int height) {
this(); // ❌ 错误:循环调用,编译错误
}
*/
// 重要规则:this()必须是构造器的第一条语句
/*
public Rectangle() {
System.out.println("初始化开始"); // ❌ 错误:必须在this()之前
this(10, 10); // 编译错误
}
*/
public void display() {
System.out.println("宽: " + width + ", 高: " + height + ", 颜色: " + color);
}
public static void main(String[] args) {
System.out.println("=== 创建对象1 ===");
Rectangle r1 = new Rectangle();
r1.display();
System.out.println("\n=== 创建对象2 ===");
Rectangle r2 = new Rectangle(20, 30);
r2.display();
System.out.println("\n=== 创建对象3 ===");
Rectangle r3 = new Rectangle(40, 50, "红色");
r3.display();
}
}
用法3:作为参数传递当前对象
java
public class ThisAsParameter {
public void methodA() {
System.out.println("methodA被调用");
methodB(this); // 将当前对象传递给methodB
}
public void methodB(ThisAsParameter obj) {
System.out.println("methodB接收到对象: " + obj);
obj.methodC(); // 通过参数调用方法
}
public void methodC() {
System.out.println("methodC被调用");
}
// 实际应用:链式调用
public ThisAsParameter setName(String name) {
System.out.println("设置名称: " + name);
return this; // 返回当前对象,支持链式调用
}
public ThisAsParameter setAge(int age) {
System.out.println("设置年龄: " + age);
return this;
}
public ThisAsParameter setCity(String city) {
System.out.println("设置城市: " + city);
return this;
}
public static void main(String[] args) {
ThisAsParameter obj = new ThisAsParameter();
// 普通调用
obj.methodA();
System.out.println("\n=== 链式调用 ===");
// 链式调用(流畅接口)
obj.setName("张三")
.setAge(25)
.setCity("北京");
// 等价于:
// obj.setName("张三");
// obj.setAge(25);
// obj.setCity("北京");
}
}
用法4:返回当前对象(用于链式调用)
java
public class PersonBuilder {
private String firstName;
private String lastName;
private int age;
private String address;
// 返回this,支持链式调用
public PersonBuilder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public PersonBuilder setAge(int age) {
this.age = age;
return this;
}
public PersonBuilder setAddress(String address) {
this.address = address;
return this;
}
public Person build() {
return new Person(firstName, lastName, age, address);
}
// 静态工厂方法
public static PersonBuilder builder() {
return new PersonBuilder();
}
// Person类
static class Person {
private String firstName;
private String lastName;
private int age;
private String address;
public Person(String firstName, String lastName, int age, String address) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return String.format("Person{firstName='%s', lastName='%s', age=%d, address='%s'}",
firstName, lastName, age, address);
}
}
public static void main(String[] args) {
// 传统的多行设置
PersonBuilder builder1 = new PersonBuilder();
builder1.setFirstName("张");
builder1.setLastName("三");
builder1.setAge(25);
builder1.setAddress("北京");
Person person1 = builder1.build();
// 链式调用(更优雅)
Person person2 = new PersonBuilder()
.setFirstName("李")
.setLastName("四")
.setAge(30)
.setAddress("上海")
.build();
// 使用静态工厂方法
Person person3 = PersonBuilder.builder()
.setFirstName("王")
.setLastName("五")
.setAge(28)
.setAddress("广州")
.build();
System.out.println(person1);
System.out.println(person2);
System.out.println(person3);
}
}
⚠️ this 使用注意事项
1. 静态上下文中不能使用 this
java
public class StaticContext {
private int instanceVar = 10;
private static int staticVar = 20;
public void instanceMethod() {
System.out.println(this.instanceVar); // ✅ 正确
System.out.println(this.staticVar); // ⚠️ 可以但不推荐(应该用类名)
}
public static void staticMethod() {
// System.out.println(this.instanceVar); // ❌ 错误:静态方法中不能使用this
// System.out.println(this.staticVar); // ❌ 错误:静态方法中不能使用this
System.out.println(staticVar); // ✅ 正确:直接访问静态变量
System.out.println(StaticContext.staticVar); // ✅ 正确:使用类名访问
}
public static void main(String[] args) {
// 静态方法中创建对象后可以使用
StaticContext obj = new StaticContext();
obj.instanceMethod(); // 可以调用实例方法
}
}
2. this 不能用在静态代码块中
java
public class StaticBlock {
private int value;
// 静态代码块
static {
// this.value = 10; // ❌ 错误:静态代码块中不能使用this
System.out.println("静态代码块执行");
}
// 实例代码块
{
this.value = 20; // ✅ 正确:实例代码块中可以使用this
System.out.println("实例代码块执行,value=" + this.value);
}
public StaticBlock() {
this.value = 30; // ✅ 正确:构造器中可以使用this
System.out.println("构造器执行,value=" + this.value);
}
}
3. this 不能指向 null
java
public class ThisNull {
private String name;
public void printName() {
// this 永远不为 null(如果为null,说明对象不存在,方法不会被调用)
System.out.println("Name: " + this.name);
}
public static void main(String[] args) {
ThisNull obj = new ThisNull();
obj.printName(); // 正常执行
// 下面的代码会抛出 NullPointerException
ThisNull nullObj = null;
// nullObj.printName(); // ❌ 运行时异常:NullPointerException
}
}
🔄 this 在内部类中的使用
普通内部类
java
public class OuterClass {
private String outerField = "外部类字段";
class InnerClass {
private String innerField = "内部类字段";
public void show() {
// 访问内部类的字段
System.out.println("内部类字段: " + this.innerField);
// 访问外部类的字段:使用 OuterClass.this
System.out.println("外部类字段: " + OuterClass.this.outerField);
// 如果字段名不冲突,也可以直接访问
System.out.println("直接访问外部类字段: " + outerField);
}
}
public void test() {
InnerClass inner = new InnerClass();
inner.show();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.test();
}
}
匿名内部类
java
public class AnonymousInnerClass {
private String field = "外部字段";
public void test() {
String localVar = "局部变量";
// 匿名内部类
Runnable runnable = new Runnable() {
private String innerField = "内部字段";
@Override
public void run() {
// 访问匿名内部类的字段
System.out.println("内部字段: " + this.innerField);
// 访问外部类的字段:使用 OuterClass.this
System.out.println("外部字段: " + AnonymousInnerClass.this.field);
// 访问局部变量(必须是final或等效final)
System.out.println("局部变量: " + localVar);
// 不能这样访问外部类的字段(this指向匿名内部类实例)
// System.out.println("错误访问: " + this.field);
}
};
new Thread(runnable).start();
}
public static void main(String[] args) {
new AnonymousInnerClass().test();
}
}
🎭 this 在继承中的使用
java
class Parent {
protected String name = "父类名称";
public void show() {
System.out.println("Parent show: " + this.name);
}
public void parentMethod() {
System.out.println("父类方法");
}
}
class Child extends Parent {
private String name = "子类名称";
@Override
public void show() {
// 访问子类的name
System.out.println("子类字段: " + this.name);
// 访问父类的name
System.out.println("父类字段: " + super.name);
// this调用的是重写后的方法(多态)
this.parentMethod(); // 调用子类重写的方法
// super调用父类的方法
super.parentMethod(); // 调用父类原始的方法
}
@Override
public void parentMethod() {
System.out.println("子类重写的方法");
}
}
public class InheritanceThis {
public static void main(String[] args) {
Child child = new Child();
child.show();
System.out.println("\n=== 多态测试 ===");
Parent parent = new Child();
parent.show(); // 调用子类的show方法
}
}
💡 this 的高级用法
1. 在枚举中使用 this
java
public enum Operation {
ADD("+") {
@Override
public int apply(int x, int y) {
return x + y;
}
},
SUBTRACT("-") {
@Override
public int apply(int x, int y) {
return x - y;
}
};
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
public abstract int apply(int x, int y);
public String getSymbol() {
return this.symbol;
}
// 使用this比较枚举值
public boolean isAdd() {
return this == ADD; // 使用this比较
}
}
2. 在接口默认方法中使用 this
java
interface Calculator {
int calculate(int a, int b);
// 默认方法中可以使用this(指向实现类的实例)
default void showInfo() {
System.out.println("Calculator实现类: " + this.getClass().getSimpleName());
}
// 静态方法中不能使用this
static void staticMethod() {
// System.out.println(this); // ❌ 错误
}
}
class SimpleCalculator implements Calculator {
@Override
public int calculate(int a, int b) {
return a + b;
}
public void test() {
// 调用接口的默认方法
this.showInfo(); // this指向SimpleCalculator实例
}
}
3. 在Lambda表达式中使用 this
java
public class LambdaThis {
private String field = "类字段";
public void testLambda() {
String localVar = "局部变量";
// Lambda表达式中的this指向外部类的实例
Runnable r = () -> {
System.out.println("Lambda中的this: " + this);
System.out.println("访问字段: " + this.field);
System.out.println("访问字段(直接): " + field);
System.out.println("访问局部变量: " + localVar);
};
// 匿名内部类中的this指向内部类实例
Runnable r2 = new Runnable() {
@Override
public void run() {
System.out.println("匿名类中的this: " + this);
System.out.println("访问外部字段: " + LambdaThis.this.field);
}
};
new Thread(r).start();
new Thread(r2).start();
}
@Override
public String toString() {
return "LambdaThis实例";
}
public static void main(String[] args) {
new LambdaThis().testLambda();
}
}
🎯 this 的常见面试题
题目1:以下代码输出什么?
java
public class Test1 {
private int value = 10;
public void print() {
int value = 20;
System.out.println("局部value: " + value);
System.out.println("成员value: " + this.value);
}
public static void main(String[] args) {
new Test1().print();
}
}
答案:
makefile
局部value: 20
成员value: 10
题目2:this() 调用有什么限制?
java
public class Test2 {
private int x;
public Test2() {
System.out.println("做一些初始化");
this(10); // 这会怎样?
}
public Test2(int x) {
this.x = x;
}
}
答案 :编译错误。this() 必须是构造器中的第一条语句。
题目3:以下代码是否正确?
java
public class Test3 {
public static void staticMethod() {
System.out.println(this);
}
}
答案 :错误。静态方法中不能使用 this。
📊 this 与 super 对比
| 特性 | this |
super |
|---|---|---|
| 指向对象 | 当前对象实例 | 父类对象实例 |
| 访问变量 | 当前类的成员变量 | 父类的成员变量 |
| 调用方法 | 当前类的方法(可能被子类重写) | 父类的方法(不会被重写影响) |
| 调用构造器 | this() 调用本类其他构造器 |
super() 调用父类构造器 |
| 使用限制 | 可以在实例方法、构造器中使用 | 可以在子类的实例方法、构造器中使用 |
| 静态上下文 | 不能在静态方法、静态块中使用 | 不能在静态方法、静态块中使用 |
🎓 最佳实践总结
1. 明确使用 this 的场景
java
public class BestPractice {
private String name;
// 场景1:区分成员变量和参数(必须使用)
public void setName(String name) {
this.name = name; // ✅ 必须使用this
}
// 场景2:构造器链(必须使用)
public BestPractice() {
this("默认名称"); // ✅ 必须使用this()
}
// 场景3:链式调用(返回this)
public BestPractice setAge(int age) {
// ... 设置年龄逻辑
return this; // ✅ 支持链式调用
}
// 场景4:没有歧义时可以省略
public void printName() {
// 这里没有局部变量name,可以直接访问
System.out.println(name); // ✅ 可以省略this
// 使用this也可以,更明确
System.out.println(this.name); // ✅ 更清晰
}
}
2. 避免滥用 this
java
public class AvoidAbuse {
private int value;
// ❌ 不必要的this(没有歧义)
public void setValue(int val) {
this.value = val; // 可以,但没有必要(参数名不同)
}
// ✅ 更好的写法
public void setValue(int value) {
this.value = value; // 必须使用this
}
// ✅ 最佳:使用不同的参数名
public void setValue(int newValue) {
value = newValue; // 不需要this,更简洁
}
}
3. 构造器中的最佳实践
java
public class ConstructorBestPractice {
private final String id; // final字段必须在构造器中初始化
private String name;
private int age;
// 主要构造器(初始化所有字段)
public ConstructorBestPractice(String id, String name, int age) {
// 参数验证
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("ID不能为空");
}
// 初始化final字段
this.id = id;
// 使用this初始化其他字段
this.name = name;
this.age = age;
}
// 辅助构造器(提供默认值)
public ConstructorBestPractice(String id) {
this(id, "未知", 0); // 调用主要构造器
}
// 辅助构造器(使用this()链)
public ConstructorBestPractice(String id, String name) {
this(id, name, 0); // 调用主要构造器
}
}
记住:this 是指向当前对象的引用 ,正确使用 this 可以让代码更清晰、更健壮,特别是在处理变量名冲突、构造器链和链式调用时非常重要!