Java学习笔记(18)--关键字this详解

来源:互联网 发布:上海英翼传媒 知乎 编辑:程序博客网 时间:2024/05/22 14:19

在整个Java中,只要是代码开发,几乎都离不开this。在Java中this可以完成三件事情:表示本类属性、表示本类方法、当前对象。

一、“this.属性”表示本类属性

讲解之前,我们先看一段代码:

package com.wz.thisdemo;class Person {    private String name ;    private int age ;    public Person(String n,int a) {              name = n ;              age = a ;    }            // setter、getter略    public String getInfo() {              return "姓名:" + name + ",年龄:" + age ;    }}public class TestDemo {    public static void main(String args[]) {              Person per = new Person("张三",20) ;              System.out.println(per.getInfo()) ;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

运行结果:

姓名:张三,年龄:20
  • 1

我们来观察一下构造方法:

    public Person(String n,int a) {              name = n ;              age = a ;    }  
  • 1
  • 2
  • 3
  • 4

这个时候的构造方法的两个参数的目的是为类中的name和age两个属性初始化,可是这个方法上的两个参数,一个是字母n,另外一个是字母a,什么意思?那么最好的做法,既然构造方法的两个参数是为了name和age属性初始化使用的,最好将其的名称也定义为name和age才最为合适:

    public Person(String name,int age) {              name = name ;              age = age ;    } 
  • 1
  • 2
  • 3
  • 4

此时构造方法上的两个参数的名称变得有意义了。但是这样一来,一个问题就出现了,发现属性没有内容了。因为在程序之中是以“{}”作为一个分界,采用就近的取用原则,所以现在为了可以明确的指定要操作的是类中属性的话,那么应该采用“this.属性”的形式完成,代码应该变为:

    public Person(String name,int age) {              this.name = name ;              this.age = age ;    }
  • 1
  • 2
  • 3
  • 4

一个开发建议: 
只要是调用本类中的属性,都使用“this.属性”的方式来进行。

二、this调用本类方法

一个类中的方法分为两种: 
(1)普通方法:如果现在要调用的是本类方法,可以使用“this.方法()”调用; 
(2)构造方法:调用构造方法使用“this(参数…)”调用。

例如:现在一个类之中存在了三个构造方法(无参、有一个参数、有两个参数),但是不管使用何种构造方法,都要求在实例化对象产生的时候输出一行提示信息:“一个新的类对象被实例化”。按照之前的学习,代码编写如下:

package com.wz.thisdemo;class Person {    private String name ;    private int age ;    public Person() {              System.out.println("*** 一个新的Person类对象被实例化。") ;    }    public Person(String name) {             System.out.println("*** 一个新的Person类对象被实例化。") ;              this.name = name ;    }    public Person(String name,int age) {             System.out.println("*** 一个新的Person类对象被实例化。") ;              this.name = name ;              this.age = age ;    }       // setter、getter略    public String getInfo() {              return "姓名:" + this.name + ",年龄:" + this.age ;    }}public class TestDemo {    public static void main(String args[]) {              Person per = new Person("张三",20) ;              System.out.println(per.getInfo()) ;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

运行结果:

*** 一个新的Person类对象被实例化。姓名:张三,年龄:20
  • 1
  • 2

不过,遗憾的是,此时的程序之中出现了大量的重复代码,而我们的目标是尽量没有重复。这种情况下就可以利用this()来完成:

package com.wz.thisdemo;class Person {    private String name ;    private int age ;    public Person() {              System.out.println("*** 一个新的Person类对象被实例化。") ;    }    public Person(String name) {              this() ;       // 调用无参构造              this.name = name ;    }    public Person(String name,int age) {             this(name) ;       // 调用有一个参数的构造              this.age = age ;    }       // setter、getter略    public String getInfo() {              return "姓名:" + this.name + ",年龄:" + this.age ;    }}public class TestDemo {    public static void main(String args[]) {              Person per = new Person("张三",20) ;              System.out.println(per.getInfo()) ;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

运行结果:

*** 一个新的Person类对象被实例化。姓名:张三,年龄:20
  • 1
  • 2

以上就使用this()就完成了构造方法之间的互相调用操作。

但是要注意的是:所有的构造方法是在对象实例化的时候被默认调用,而且是在调用普通方法之前调用,所以使用“this()”调用构造方法的操作,一定要放在构造方法的首行;

    public Person(String name) {              this() ;       // 调用无参构造,放在首行              this.name = name ;    }
  • 1
  • 2
  • 3
  • 4

另外,我们来看一段代码:

package com.wz.thisdemo;class Person {    private String name ;    private int age ;    public Person() {              this("",10) ;       // 调用两个参数的构造              System.out.println("*** 一个新的Person类对象被实例化。") ;    }    public Person(String name) {              this() ;       // 调用一个参数的构造              this.name = name ;    }    public Person(String name,int age) {              this(name) ;       // 调用有一个参数的构造              this.age = age ;    }       // setter、getter略    public String getInfo() {              return "姓名:" + this.name + ",年龄:" + this.age ;    }}public class TestDemo {    public static void main(String args[]) {              Person per = new Person("张三",20) ;              System.out.println(per.getInfo()) ;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

运行结果:

Exception in thread "main" java.lang.Error: Unresolved compilation problems:     Recursive constructor invocation Person(String, int)    Recursive constructor invocation Person()    Recursive constructor invocation Person(String)    at com.wz.thisdemo.Person.<init>(TestDemo.java:6)    at com.wz.thisdemo.TestDemo.main(TestDemo.java:23)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通过以上代码和运行结果不难看出:递归调用了构造器。

所以,如果一个类之中存在了多个构造方法的话,并且这些构造方法都使用了this()互相调用,那么至少要保留一个构造方法没有调用其他构造,以作为程序的出口。

我们来看一个构造方法互相操作的实例: 
定义一个雇员类(员工号、姓名、薪水、部门),在这个类中提供四个工作方法: 
A、单参,只传递员工号,则员工姓名:无名氏,薪水:0,部门:未定 
B、双参,传递员工号,姓名,则员工薪水为1000,部门:后勤 
C、四参,传递员工号,姓名,部门,薪水 
D、无参,则均为空值 
来看代码:

package com.wz.thisdemo;class Emp {    private int empno ;    private String ename ;    private double salary ;    private String dept ;    public Emp(){}    public Emp(int empno){              this.empno = empno ;              this.ename = "无名氏" ;              this.salary = 0.0 ;              this.dept = "未定" ;    }    public Emp(int empno,String ename){              this.empno = empno ;              this.ename = ename ;              this.salary = 1000.0 ;              this.dept = "后勤" ;    }    public Emp(int empno,String ename,double salary,String dept){              this.empno = empno ;              this.ename = ename ;              this.salary = salary ;              this.dept = dept ;    }    public String getInfo() {              return "雇员编号:" + this.empno + ",姓名:" + this.ename + ",工资:" + this.salary + ",部门:" + this.dept ;    }}public class TestDemo {    public static void main(String args[]) {        Emp emp1 = new Emp();        System.out.println(emp1.getInfo());        Emp emp2 = new Emp(4555);        System.out.println(emp2.getInfo());        Emp emp3 = new Emp(6542,"小王");        System.out.println(emp3.getInfo());        Emp emp4 = new Emp(4578,"小明",12000,"技术部");        System.out.println(emp4.getInfo());    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

运行结果:

雇员编号:0,姓名:null,工资:0.0,部门:null雇员编号:4555,姓名:无名氏,工资:0.0,部门:未定雇员编号:6542,姓名:小王,工资:1000.0,部门:后勤雇员编号:4578,姓名:小明,工资:12000.0,部门:技术部
  • 1
  • 2
  • 3
  • 4

如果按照以上的方式开发,是可以完成功能的实现,但是代码中却存在了重复的代码,很明显,这样不合适。于是,我们通过构造方法的相互调用来对构造方法进行如下改动:

    public Emp(){}    public Emp(int empno){              this(empno,"无名氏",0.0,"未定") ;//调用四参构造方法    }    public Emp(int empno,String ename){              this(empno,ename,1000.0,"后勤") ;//调用四参构造方法    }    public Emp(int empno,String ename,double salary,String dept){              this.empno = empno ;              this.ename = ename ;              this.salary = salary ;              this.dept = dept ;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行结果如下:

雇员编号:0,姓名:null,工资:0.0,部门:null雇员编号:4555,姓名:无名氏,工资:0.0,部门:未定雇员编号:6542,姓名:小王,工资:1000.0,部门:后勤雇员编号:4578,姓名:小明,工资:12000.0,部门:技术部
  • 1
  • 2
  • 3
  • 4

这种构造方法的互相调用是在对象实例化的时候,不同的构造有一些相同操作的情况下去使用。

三、this表示当前对象

当前对象,是指当前正在调用类中方法的对象。

先来看一段代码:

package com.wz.thisdemo;class Book{}public class TestDemo {    public static void main(String args[]) {        Book booka = new Book();        System.out.println(booka);        Book bookb = new Book();        System.out.println(bookb);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行结果:

com.wz.thisdemo.Book@15db9742com.wz.thisdemo.Book@6d06d69c
  • 1
  • 2

在Book类中加上一个打印this的方法:

package com.wz.thisdemo;class Book{    public void print(){        //this就是当前调用该方法的对象        System.out.println("this = "+ this);    }}public class TestDemo {    public static void main(String args[]) {        Book booka = new Book();        System.out.println(booka);        booka.print();        System.out.println();        Book bookb = new Book();        System.out.println(bookb);        bookb.print();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行结果:

com.wz.thisdemo.Book@15db9742this = com.wz.thisdemo.Book@15db9742com.wz.thisdemo.Book@6d06d69cthis = com.wz.thisdemo.Book@6d06d69c
  • 1
  • 2
  • 3
  • 4
  • 5

那么,之前的“this.属性”实际上就是当前对象的属性,一定是堆内存中保存的内容。

原创粉丝点击