28_this 关键字
this 的基本概念
-
若在构造方法中出现了this关键字,则代表当前正在构造的对象。
-
若在成员方法中出现了this关键字,则代表当前正在调用的对象。
-
this 关键字本质上就是当前类类型的引用变量。
/* 编程实现this关键字的使用 */ public class ThisTest { // 自定义构造方法 ThisTest() { // 若在构造方法中出现了this关键字,则代表当前正在构造的对象 System.out.println("构造方法中:this = " + this); } // 自定义成员方法 void show() { // 若在成员方法中出现了this关键字,则代表当前正在调用的对象 System.out.println("成员方法中:this = " + this); } public static void main(String[] args) { // 1、声明 ThisTest 类型的引用指向该类型的对象 ThisTest tt = new ThisTest(); // 构造方法中:this = ThisTest@20ce78ec // 2、调用show方法 System.out.println("main 方法中:tt = " + tt); // main 方法中:tt = ThisTest@393671df tt.show(); // 成员方法中:this = ThisTest@393671df } }
this 关键字的工作原理
-
在构造方法中和成员方法中访问成员变量时,编译器会加上this.的前缀,而this.相当于汉语中的“我的”,当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同,从而this.方式访问的结果也就随之不同。
// 自定义成员方法实现所有特征的打印 隐含着this关键字,this关键字当前正在调用的对象 在底层中name 就是 this.name // 在成员方法中为什么能直接访问成员变量?因为成员方法中默认使用this.去访问的 // this的价值:始终代表当前对象 void show() { System.out.println("我是" + this.name +",今年" + this.age + "岁了!"); }
使用方式
-
编写构造方法时尽可能的让形参变量名和成员变量名一致,这样可以提高代码的可读性。
-
public class Person { String name; int age; // 这样构造出来的对象name属性值和age属性值都会被赋上默认值,即:null 和 0 // 为什么?就近原则 懒人原则:此时,当我们的形参变量名和成员变量名相同时,当我们在方法体中想用name和age这两个变量时,既可以用形参变量的name和age,又可以使用成员变量的name和age。所谓的就近原则就是:既然这两组变量我都能用,我就用近点的呗,就直接使用了形参变量的name和age Person(String name, int age) { name = name; // 根据就近原则,我们就是形参自己给自己赋值了,跟成员变量没关系,此时成员变量就使用默认值了,这就是出现错误的原因。为了体验出这里左边是对象中成员变量的name和age,此处就应该写成this.name = name; this.age = age;在构造方法和成员方法中隐含的本类类型对象的引用就是this。 // 加this.前缀就是为了告诉编辑器,这个name和age是 我的 name 和 age , 我就是当前正在构造的对象 // 何时需要加this.前缀?形参名和成员变量名同名时,需要加,因为根据就近原则,有歧义,我们需要明确声明它是成员变量 age = age; } }
-
当局部变量名和成员变量名相同时,在方法体中会优先使用局部变量(就近原则:局部变量包括形参变量),若希望使用成员变量,则需要在成员变量的前面加上this.的前缀,明确要求该变量是成员变量(重中之重)。
-
this关键字除了可以通过this.的方式调用成员变量(this.name this.age)和成员方法(this.show() this.grow() 这个是指在成员方法中调用成员变量和成员方法,当然this.在没有歧义的时候也可以省略)外,还可以作为方法的返回值(重点)。
// 自定义成员方法实现Person类型对象的获取并返回的行为 // String getName() {} Person getPerson() { // 返回当前调用对象本身,也就是谁调用这个方法,我就把谁原模原样的返回出去 也可以:Person tp = new Person(); return tp; return this; } System.out.println("---------------------------------------------------"); // 5、调用成员方法去获取对象 Person p5 = p1.getPerson(); System.out.println("p1 = " + p1); // p1 = Person@5c6648b0 System.out.println("p5 = " + p5); // p5 = Person@5c6648b0 // p1 和 p5指向的是同一个堆区内存空间,也就是p1和p5是同一个对象。 p1.show(); // 我是张飞,今年32岁了! p5.grow(); p1.show(); // 我是张飞,今年34岁了!
-
在构造方法的第一行可以使用 this() 的方式来调用本类中的其它构造方法(了解)。为什么放在第一行?若不放在第一行,在前面对类的一些东西进行操作,如成员变量,那么操作后再调用this()就会重复操作,故而规定了只能在第一行
/* 编程实现Boy类的定义 */ public class Boy { String name; // 用于描述姓名的成员变量 // 自定义构造方法 Boy() { // 调用本类中的有参构造方法 this("无名"); System.out.println("无参构造方法!"); } Boy(String name) { this(); System.out.println("=======有参构造方法!"); this.name = name; } // 自定义成员方法实现特征的打印 void show() { System.out.println("我的名字是:" + name); } public static void main(String[] args) { // 1、使用有参方式构造对象并打印特征 Boy b1 = new Boy(); b1.show(); // null 无名 System.out.println("---------------------------------------"); // 2、使用无参方式构造对象并打印特征 Boy b2 = new Boy("张飞"); b2.show(); // 张飞 } } Boy.java:9: 错误: 递归构造器调用 Boy() { ^ 1 个错误 错误: 编译失败 故而,不能在无参构造器调有参构造器的同时,有参构造器也在调用无参构造器
引用类型的注意事项
-
引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象。
-
当某个引用类型变量为null时无法对对象实施访问(因为它没有指向任何对象)。此时,如果通过引用访问成员变量或调用方法,会产生 NullPointerException异常(空指针异常)。
// 3、引用变量的数值可以为空 // Boy b3 = null; // b3.show(); // 编译 ok, 运行会发生 NullPointerException 空指针异常 算术异常、数组下标越界异常 Boy b3 = b2; b3.show(); // 张飞