欢迎光临
我们一直在努力

Java面向对象程序设计——this关键字

一、先给一道例题

在Java程序开发中,我们经常需要比较两个对象是否“相等”。例如,在学生管理系统中,我们需要判断两个学生的姓名和年龄是否完全一致,以确认是否为同一个人。请设计一个Person类,要求如下:

  • Person类包含两个私有属性:name(姓名)和age(年龄)。

  • 提供带参构造方法,用于创建对象并完成属性初始化。

  • 提供一个compareTo方法,接收另一个Person对象作为参数,判断当前对象与传入对象是否相等(姓名和年龄均相同返回true,否则返回false)。

  • 在构造方法和比较方法中,使用this关键字来区分成员变量和参数。

  • 编写测试类,创建两个Person对象,调用compareTo方法进行比较,并输出结果。

  • 二、解题思路

    2.1 this关键字的核心概念

    this关键字在Java中代表当前对象的引用,即它指向当前正在执行方法或构造函数的那个对象实例。每一次通过new关键字创建对象,Java虚拟机就会在堆内存中为该对象分配一块空间,而this关键字指向的就是这块空间,相当于“我自己的地址”。

    简单来说,this在程序中的含义就是“我这个对象”。普通方法中,this指向调用该方法的对象;构造方法中,this指向正在初始化的对象。这种理解对于掌握它的各种用法至关重要。

    2.2 为什么需要this关键字

    在类的设计过程中,经常出现变量名冲突的情况。当方法的参数名(或局部变量名)与类的成员变量名同名时,如果不加任何区分,编译器会优先使用方法参数(遵循“就近原则”),成员变量就会无法被正确赋值。

    此外,同一个类中往往存在多个构造方法,它们之间通常有一些共同的初始化逻辑。如果每个构造方法中都重复编写相同的代码,不仅冗余,维护起来也很麻烦。利用this()可以在一个构造方法中调用另一个构造方法,实现代码复用。

    2.3 this关键字的核心用法

    this关键字在Java中有以下几种主要的用法:

  • 区分成员变量和局部变量:当方法参数或局部变量与实例变量同名时,使用this.变量名表示当前对象的实例变量,解决“变量遮蔽”问题。这是最常见的用法。

  • 调用本类的其他构造方法:在一个构造方法中,使用this(参数)调用本类的另一个构造方法,减少重复代码。调用语句必须放在构造方法的第一行。

  • 调用本类的其他成员方法:在实例方法中使用this.方法名()调用当前类的其他成员方法。虽然大多数情况下可以省略this,但在某些需要明确指代当前对象的场景中显式写出,有助于提高代码可读性。

  • 作为方法的返回值返回当前对象:在方法中返回this,可以实现方法链式调用,在设计构建器模式等场景中十分常用。

  • 作为参数传递给其他方法:将当前对象作为参数传递给其他方法或服务,常见于注册监听器、添加到管理器、事件发布等场景。

  • 2.4 this关键字的使用限制

    this关键字不能在static修饰的静态方法中使用,因为静态方法是属于类的,不需要通过对象来调用,而this是对象级别的引用,在静态方法中根本不存在。

    理解这一点的关键在于:静态方法随着类的加载而存在,此时可能还没有任何对象被创建,因此this无法指向任何“当前对象”。

    三、代码实现与逐行解释

    3.1 完整代码

    java

    /**
    * Person类 – 使用this关键字进行对象比较
    * 例题:定义Person类,包含name和age属性,提供compareTo方法判断两个对象是否相等
    */
    class Person {
    // ———- 私有属性 ———-
    private String name; // 姓名
    private int age; // 年龄

    /**
    * 带参构造方法
    * 使用this关键字将参数值赋给成员变量,解决局部变量与成员变量的名称冲突
    * @param name 姓名
    * @param age 年龄
    */
    public Person(String name, int age) {
    // this.name表示成员变量,name表示构造方法的形参(局部变量)
    this.name = name; // 将传入的name赋给当前对象的name属性
    this.age = age; // 将传入的age赋给当前对象的age属性
    }

    /**
    * 比较方法:判断当前对象与传入的Person对象是否相等
    * 使用this关键字代表当前对象,通过this访问当前对象的成员变量和成员方法
    * @param p 需要比较的另一个Person对象
    * @return 如果两个对象的name和age完全相同则返回true,否则返回false
    */
    public boolean compareTo(Person p) {
    // this代表调用该方法的对象(当前对象)
    // p代表传入的参数对象(另一个Person)
    // 两个对象相互比较:当前对象的名字和年龄是否分别等于传入对象的名字和年龄
    return this.name.equals(p.name) && this.age == p.age;
    }

    /**
    * 获取姓名(getter方法)
    * @return 姓名
    */
    public String getName() {
    return name;
    }

    /**
    * 设置姓名(setter方法)
    * setter方法中也可以使用this关键字来区分成员变量和形参
    * @param name 姓名
    */
    public void setName(String name) {
    this.name = name;
    }

    /**
    * 获取年龄(getter方法)
    * @return 年龄
    */
    public int getAge() {
    return age;
    }

    /**
    * 设置年龄(setter方法)
    * @param age 年龄
    */
    public void setAge(int age) {
    this.age = age;
    }
    }

    /**
    * 测试类 – 演示this关键字的使用
    */
    public class ThisKeywordDemo {
    public static void main(String[] args) {
    // 创建第一个Person对象:mary,20岁
    Person p1 = new Person("mary", 20);
    // 创建第二个Person对象:smith,30岁
    Person p2 = new Person("smith", 30);
    // 创建第三个Person对象:mary,20岁(与p1同名同年龄)
    Person p3 = new Person("mary", 20);

    // 调用compareTo方法比较p1和p2
    System.out.println("p1和p2比较的结果 = " + p1.compareTo(p2));
    // 调用compareTo方法比较p1和p3
    System.out.println("p1和p3比较的结果 = " + p1.compareTo(p3));
    }
    }

    运行结果:

    text

    p1和p2比较的结果 = false
    p1和p3比较的结果 = true

    3.2 逐行代码解释

    ① 构造方法中的this:区分成员变量和局部变量

    java

    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    在构造方法中,参数name和成员变量name同名。如果不加this,写成name = name,那么两个name都指的是构造方法的参数(局部变量),赋值操作只是将参数赋值给它自己,成员变量name不会被修改,最终对象的姓名将保持默认值null。

    为了解决这个问题,this.name明确表示“当前对象的name属性”,而name(不带this)表示方法的形参。这里使用this将形参的值赋给当前对象的成员变量,完成对象初始化。

    ② 比较方法中的this:代表当前对象

    java

    public boolean compareTo(Person p) {
    return this.name.equals(p.name) && this.age == p.age;
    }

    在compareTo方法中,this代表调用该方法的对象。当p1.compareTo(p2)被执行时,this指向p1对象;p指向传入的参数p2对象。this.name读取的是p1的姓名,p.name读取的是p2的姓名。

    许多初学者误以为this只能在构造方法中使用,但实际上,在普通实例方法中使用this也非常普遍。this在这种场景下的含义是“哪个对象调用了这个方法,this就代表哪个对象”。

    ③ setter方法中的this:同样用于区分同名变量

    java

    public void setName(String name) {
    this.name = name;
    }

    在setName()方法的参数中也出现了同名的name变量,同样需要通过this.name将形参的值赋给成员变量。this在此处起到了和构造方法中完全相同的作用——解决变量命名冲突。

    ④ 测试类中的调用过程

    java

    Person p1 = new Person("mary", 20);
    Person p3 = new Person("mary", 20);
    System.out.println("p1和p3比较的结果 = " + p1.compareTo(p3));

    创建两个同名同年龄的Person对象,调用p1.compareTo(p3),this指向p1,p指向p3,通过this.name.equals(p.name)和this.age == p.age分别比较姓名和年龄,由于两者都相等,最终结果为true。

    3.3 进阶用法示例:构造方法之间的调用

    除了上述例题中展示的用法之外,this还可以用于构造方法之间的相互调用。以下代码展示了这一用法:

    java

    /**
    * 进阶示例:使用this()调用本类其他构造方法
    */
    class Employee {
    private String name;
    private int age;
    private String department;

    /**
    * 三参数构造方法
    * @param name 姓名
    * @param age 年龄
    * @param department 部门
    */
    public Employee(String name, int age, String department) {
    this.name = name;
    this.age = age;
    this.department = department;
    }

    /**
    * 双参数构造方法
    * 通过this(name, age, "未分配")调用三参数构造方法,避免重复代码
    * 注意:this()调用语句必须是构造方法中的第一条语句
    */
    public Employee(String name, int age) {
    this(name, age, "未分配"); // 调用三参数构造方法,部门默认为"未分配"
    System.out.println("双参数构造方法被调用");
    }

    /**
    * 无参构造方法
    * 通过this("default", 0)调用双参数构造方法,设置默认值
    */
    public Employee() {
    this("default", 0); // 调用双参数构造方法
    System.out.println("无参构造方法被调用");
    }
    }

    在这个Employee类中,三个构造方法通过this()实现了链式调用:

    • 无参构造方法调用双参数构造方法this(“default”, 0)

    • 双参数构造方法调用三参数构造方法this(name, age, “未分配”)

    • 最终三参数构造方法完成实际的属性初始化工作

    this()调用时必须遵循以下三点注意事项:

  • 只能在构造方法中使用this(),不能在普通成员方法中使用

  • this()必须是构造方法中的第一条语句,否则编译时会报错

  • 不能形成循环调用,即构造方法A调用构造方法B的同时构造方法B又调用构造方法A,这种写法会导致无限递归并引发编译错误

  • 3.4 进阶用法示例:链式调用

    this作为返回值返回当前对象,可以实现方法链式调用,使代码更加简洁优雅:

    java

    /**
    * 链式调用示例 – 使用this作为返回值
    */
    class Student {
    private String name;
    private int age;
    private String major;

    // setName返回this,支持链式调用
    public Student setName(String name) {
    this.name = name;
    return this;
    }

    public Student setAge(int age) {
    this.age = age;
    return this;
    }

    public Student setMajor(String major) {
    this.major = major;
    return this;
    }

    public void showInfo() {
    System.out.println("姓名:" + name + ",年龄:" + age + ",专业:" + major);
    }

    public static void main(String[] args) {
    // 链式调用:一个语句中连续调用多个setter方法
    Student stu = new Student()
    .setName("张三")
    .setAge(20)
    .setMajor("计算机科学与技术");
    stu.showInfo();
    }
    }

    每一行代码都由this返回当前对象的引用,因此可以像串糖葫芦一样依次“点”出下一个方法,形成流畅的调用链条。这种写法在Java标准库的StringBuilder、构建器模式等场景中随处可见。

    3.5 进阶用法示例:this作为参数传递

    this还可以代表当前对象,作为实参传递给其他方法:

    java

    /**
    * 作为参数传递 – 将当前对象传递给其他方法
    */
    class Printer {
    // 打印任意对象的信息
    public static void print(Object obj) {
    System.out.println("打印对象:" + obj);
    }
    }

    class Document {
    private String content;

    public Document(String content) {
    this.content = content;
    }

    public void print() {
    // 将当前对象(this)传递给Printer的print方法
    Printer.print(this);
    }

    @Override
    public String toString() {
    return "Document{content='" + content + "'}";
    }

    public static void main(String[] args) {
    Document doc = new Document("Hello Java");
    doc.print(); // 输出:打印对象:Document{content='Hello Java'}
    }
    }

    在print()方法中调用Printer.print(this),将当前Document对象的引用传递给Printer的静态方法。实际应用中,这种模式常见于事件监听器的注册、对象入队添加到管理器等场景,比如eventBus.register(this)或service.addHandler(this)。

    四、总结

    通过以上Person类对象比较的例题,我们可以总结出以下几个核心要点:

    this关键字的本质

    • this代表当前对象的引用,指向当前正在执行方法或构造方法的那个对象实例

    • 普通方法中,this指向调用该方法的对象;构造方法中,this指向正在初始化的对象

    • this本质上是一个“隐式参数”,JVM在调用实例方法时会自动将当前对象的引用传递给this

    this关键字的核心用法

    • 区分成员变量和局部变量:当方法参数或局部变量与成员变量同名时,使用this.变量名明确访问成员变量,这是最常见的用法,同时也是解决“变量遮蔽”问题的标准做法

    • 调用本类的其他构造方法:在构造方法的第一行使用this(参数列表)调用本类的另一个构造方法,实现构造器间的代码复用

    • 调用本类的其他成员方法:使用this.方法名()调用当前类的其他实例方法,虽然多数情况下可以省略,但在需要明确指代时显式写出有助于提高可读性

    • 作为方法的返回值:在方法中返回this,可以实现方法的链式调用,这种“流式API”在现代Java框架中无处不在

    • 作为参数传递给其他方法:将当前对象作为参数传递给其他方法,常见于注册监听器、添加到管理器等场景

    this关键字的使用限制与注意事项

    • this不能在static修饰的静态方法中使用,因为静态方法属于类而不是对象,静态方法中没有“当前对象”的概念

    • this()调用构造方法的形式中,this()必须是所在构造方法中的第一条语句,且只能出现一次,否则编译报错

    • 不能在一个类中让两个构造方法通过this()循环调用,否则会引发编译错误

    • 在非静态内部类中,this指向内部类自身,若要引用外部类的实例,需要使用外部类名.this的形式

    • 虽然可以通过命名规范(如给参数加前缀p)来避免命名冲突,但在标准Java编码中,使用this是更清晰、更主流的做法

    this与super的区别

    • this指向当前类的对象实例,super指向父类的对象实例

    • this()调用本类的其他构造方法,super()调用父类的构造方法

    • this()和super()都必须在构造方法的第一行,因此它们不能同时出现在同一个构造方法中

    this关键字的实际应用场景

    • 构造方法中的初始化:在构造方法中使用this.属性 = 参数完成对象的初始化,这是几乎所有Java类的基本写法

    • 对象之间的比较:如例题中的compareTo方法,使用this代表当前对象与传入对象进行比较

    • 构建器模式(Builder Pattern) :每个setter方法都返回this,形成流畅的调用接口

    • 事件监听器注册:将this作为参数传递给事件注册方法,使当前对象能够接收事件通知

    • 日志与调试:将this作为参数传递给日志记录方法,记录当前对象的状态信息

    五、更多练习题目推荐

    以下是可以直接访问的Java this关键字相关练习题(请复制链接后自行替换 [colon] 为 :,[dot] 为 .):

    https://blog.csdn.net/qq_41167281/article/details/127281846

    https://blog.csdn.net/weixin_44204699/article/details/118453083

    https://blog.csdn.net/qq_1846311374/article/details/149280316

    https://www.nowcoder.com/practice/2e5e331d9cfc4010b9a5cf0faa2de3c9

    https://www.luogu.com.cn/problem/P5740

    https://blog.csdn.net/2401_87890252/article/details/152521736

    练习建议:可以尝试修改Person类,增加更多属性(如性别、学号),并扩展compareTo方法进行比较。也可以尝试为Person类实现多个构造方法(无参、双参、三参),并通过this()实现构造方法之间的调用,体会构造器链如何避免重复代码。还可以尝试为自己设计的类添加链式调用的setter方法,体验流畅API带来的代码简洁之美。

    赞(0)
    未经允许不得转载:171主机测评 » Java面向对象程序设计——this关键字
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址