1

具体内容

在 Java 程序中,当局部变量全局变量数据类型和名称都相同的时,此时全局变量会被隐藏而变得不能使用。即:局部变量会覆盖掉全局变量

在 Java 程序中,利用 this 关键字可以显示类属性的调用、类方法的调用、表示当前对象。

使用 this 的语法格式如下:

this.成员变量名
this.成员方法名()

this 具体使用

调用成员变量

Demo.java

// 定义一个内部类 BookInfo
class BookInfo {
    //  内部类的属性
    String title;
    double price;

    //  内部类的方法
    public void getInfo() {
        // 打印的结果是当前对象的属性,是当前对象
        System.out.println("图书名称:" + this.title + ",价格为:" + this.price);
    }
}

public class Demo {

    public static void main(String[] args) {
        // 实例化 两个BookInfo 的对象
        BookInfo bookA = new BookInfo();
        BookInfo bookB = new BookInfo();

        // 给 bookA 增加属性
        bookA.price = 89.8;
        bookA.title = "Java 开发"; // 给 booA 这个对象赋值,

        // 给 bookB 增加属性
        bookB.price = 69.8;
        bookB.title = "JSP 开发"; // 给 booB 这个对象赋值
        
        // 分别调用 getInfo() 方法
        bookA.getInfo();
        bookB.getInfo();
    }
}

控制台输出

图书名称:Java 开发,价格为:89.8
图书名称:JSP 开发,价格为:69.8

说明

通过控制台的输出,可以看到程序上面实例化的两个对象:bookA、bookB,分别通过 getInfo() 打印出来的数据都是自己的,即在调用 BookInfo 中的 getInfo() 时,调用时候的 this 就是执行当时的调用对象。例如:当 bookA 调用 getInfo() 时,当前的 this 就是指的是 bookA。

成员变量的作用域

Demo.java

class BookInfo {
    String title;
    double price;

    public void getInfo() {
        String title = "我是默认值";    // 局部变量
        
        // 输出的结果也为局部变量
        System.out.println("title 值为:"+ title);  
        
        // 输出的结果为全局变量
        System.out.println("图书名称:" + this.title + ",价格为:" + this.price);     
    }
}

public class Demo {

    public static void main(String[] args) {
        // 实例化 BookInfo 对象
        BookInfo bookA = new BookInfo();
        //  给  bookA 增加属性
        bookA.price = 89.8;
        bookA.title = "Java 开发";

        bookA.getInfo();
    }
}

控制台输出

title 值为:我是默认值
图书名称:Java 开发,价格为:89.8

说明

如果我们在 BookInfo 类中的 getInfo() 方法中,全部都是使用 title,而不是使用 this.title,那么输出的结果就全部为 我是默认值。 那是因为我们的定义了局部变量,如果没有 this 关键字去声明,那么所有的 title 引入的指向都是 当前的局部变量。在上面的程序代码中就是:我是默认值。

反过来看,当我们加上了 this 关键字,就是表示当前的对象,而 this.title 就是指的是我们定义的全局的属性了。

调用成员方法

使用传统的方式

在使用 this 关键字之前,我们先看下传统的方法。在下面的代码中有四个构造器方法。分别使用这四个构造器方法去创建对象。并且输出结果。

TestDemo.java

class Emp{
    
    private int empno;
    private String ename;
    private double sal;
    private String dept;
    
    public Emp() {
        this.empno = 0;
        this.ename = "无名氏";
        this.sal = 0.0;
        this.dept = "无";
    }
    
    public Emp(int empno){
        this.empno = empno;
        this.ename = "临时工";
        this.sal = 200;
        this.dept = "测试组";
    }
    
    public Emp(int empno, String ename){
        this.empno = empno;
        this.ename = ename;
        this.sal = 2000.0;
        this.dept = "技术部";
    }
    
    public Emp(int empno, String ename, double sal, String dept){
        this.empno = empno;
        this.ename = ename;
        this.sal = sal;
        this.dept = dept;
    }
    
    public String getInfo() {
        return "雇员编号:" + this.empno + ", 雇员名称" + this.ename + ", 工资" + this.sal + ",部门"+ this.dept;
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Emp emp1 = new Emp();
        Emp emp2 = new Emp(2);
        Emp emp3 = new Emp(3, "张三");
        Emp emp4 = new Emp(4, "张三", 5000, "经理部");
        
        System.out.println(emp1.getInfo());
        System.out.println(emp2.getInfo());
        System.out.println(emp3.getInfo());
        System.out.println(emp4.getInfo());
        
    }
}

控制台输出

雇员编号:0, 雇员名称无名氏, 工资0.0,部门无
雇员编号:2, 雇员名称临时工, 工资200.0,部门测试组
雇员编号:3, 雇员名称张三, 工资2000.0,部门技术部
雇员编号:4, 雇员名称张三, 工资5000.0,部门经理部

使用 this 调用方法

接下来,我们使用 this 来改写,上面的写法肯定不是最优的方案。因为存在好多的重复性的代码。然后我们使用 this 来重构。但是在下面的代码中,需要留有一个 this 出口。
++出口是指的是:我们在创建构造器的时候,不能每一个 构造器方法中都使用 this() 方法,因为如果全部都使用,程序执行的就会陷入“递归调用” 就会报错。++

在下面的代码中,我们需要了解的知识是:this() 就是指我们当前的调用的构造器方法。

TestDemo.java

package com.wq.study.reference;

class Emp{
    
    private int empno;
    private String ename;
    private double sal;
    private String dept;
    
    public Emp() {
        // 我们通过使用 this() 方法来调用我们的 四参构造方法
        this(0, "无名氏", 0.0, "无");     // 当前一行就可以替换下面的四行代码
        
        /*由于改写,这段代码就注释掉
        this.empno = 0;
        this.ename = "无名氏";
        this.sal = 0.0;
        this.dept = "无";*/
    }
    
    public Emp(int empno){
        this(empno, "临时工", 200, "测试");    // 在这个地方我们也使用 this() 方法来改写
        
        /* 由于改写,这段代码就注释掉
        this.empno = empno;
        this.ename = "临时工";
        this.sal = 200;
        this.dept = "测试组";*/
    }
    
    public Emp(int empno, String ename){
        this(empno, ename, 2000, "技术部");    // 同样我们使用 this() 方法来改写
        
        /* 由于改写,这段代码就注释掉
        this.empno = empno;
        this.ename = ename;
        this.sal = 2000.0;
        this.dept = "技术部";*/
    }
    
    public Emp(int empno, String ename, double sal, String dept){
        // 我们这个地方留有出口。就不会导致产生递归调用而报错
        this.empno = empno;
        this.ename = ename;
        this.sal = sal;
        this.dept = dept;
    }
    
    public String getInfo() {
        return "雇员编号:" + this.empno + ", 雇员名称" + this.ename + ", 工资" + this.sal + ",部门"+ this.dept;
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Emp emp1 = new Emp();
        Emp emp2 = new Emp(2);
        Emp emp3 = new Emp(3, "张三");
        Emp emp4 = new Emp(4, "张三", 5000, "经理部");
        
        System.out.println(emp1.getInfo());
        System.out.println(emp2.getInfo());
        System.out.println(emp3.getInfo());
        System.out.println(emp4.getInfo());
    }
}

控制台输出

雇员编号:0, 雇员名称无名氏, 工资0.0,部门无
雇员编号:2, 雇员名称临时工, 工资200.0,部门测试
雇员编号:3, 雇员名称张三, 工资2000.0,部门技术部
雇员编号:4, 雇员名称张三, 工资5000.0,部门经理部

说明

从控制台的输出可以看出,这个两个结果是没有区别的,即说明我们改写成功,但是需要有一点说明就是一定要在某一个 构造方法中留有出口。

this 表示当前对象

this 表示当前的对象,其实还是比较好理解。我们通过以下代码来了解。

Demo.java

class BookInfo {
    
    public void getInfo() {
        System.out.println("this ="+ this);
    }
}

public class Demo {

    public static void main(String[] args) {
        BookInfo bookA = new BookInfo();
        System.out.println("bookA:"+bookA);
        bookA.getInfo();
        System.out.println("--------------------");
        BookInfo bookB = new BookInfo();
        System.out.println("bookB:"+bookB);
        bookB.getInfo();
    }
}

控制台

bookA: BookInfo@7852e922
this = BookInfo@7852e922
--------------------
bookB: BookInfo@4e25154f
this = BookInfo@4e25154f

说明

我们打印出来的消息可以看到,this 就是当前的对象地址,指的是当前的调用的对象。

通过复杂的代码理解 this

对于 this 的理解,我们可以通过下面的复杂点的代码来理解。代码上面有详细的注释。大家仔细看就好了。

class A{
    private B b;    // 将 B 作为私有的成员变量
    public A() {
        this.b = new B(this);    // 2.实例化对象b,将当前的this(指的是 A)传递到B的构造器中, 并且将实例化出来的 B对象  给到 A 对象中的 B(为 A 对象中的私有成员变量)
        this.b.get();            // 4.通过 b 调用 get() 方法
    }
    
    public void print() {
        System.out.println("Hello word!");    // 6.打印输出 Hello word!
    }
}

class B{
    private A a;    // 将 A 作为私有的成员变量
    public B(A a) {
        this.a = a;        // 3.将传递过来的 A 赋值给 自己的私有变量 A,由于作用域的关系,this指向的是 B
    }
    
    public void get() {
        this.a.print();        // 5.通过这个地方调用 A的 print()
    }
}

public class Demo {

    public static void main(String[] args) {
        A temp = new A();        // 1.实例化对象 A
    }
}

总结

  1. 类中的属性调用以后都要加上 this
  2. 类中的构造方法间的互相调用,一定要保留有出口(即存在有一个构造方法没有使用 this() )
  3. this 表示当前对象,指的是当前正在调用类中的方法的对象,this 不是一个固定的。

Wayfreem
241 声望33 粉丝

一个后端工程师,偏偏喜欢前端。