4. this 引用
4.1 为什么要有this引用
先看一个日期类的例子:
public class Date { public int year; public int month; public int day; public void setDay(int y, int m, int d){ year = y; month = m; day = d; } public void printDate(){ System.out.println(year + "/" + month + "/" + day); } public static void main(String[] args) { // 构造三个日期类型的对象 d1 d2 d3 Date d1 = new Date(); Date d2 = new Date(); Date d3 = new Date(); // 对d1,d2,d3的日期设置 d1.setDay(2023,8,1); d2.setDay(2023,8,2); d3.setDay(2023,8,3); // 打印日期中的内容 d1.printDate(); d2.printDate(); d3.printDate(); } }
以上代码定义了一个日期类,然后main方法中创建了三个对象,并通过 Date 类中的成员方法对对象进行设置和打印,代码整体逻辑非常简单,没有任何问题。
但是仔细想想有两个疑问:
1.形参名不小心与成员变量名相同:
public void setDay(int year, int month, int day){ year = year; month = month; day = day; }
那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?
2.三个对象都在调用 setDate 和 printDate 函数,但是这两个函数中没有任何有关对象的说明, setDate 和 printDate 函数如何知道打印的是那个对象的数据呢?
一切让this引用来揭开这层神秘的面纱
4.2 什么是this引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。
只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
public class Date { public int year; public int month; public int day; public void setDay(int year, int month, int day) { this.year = year;//this引用的是调用成员方法的对象。 this.month = month; this.day = day; } public void printDate() { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date d = new Date(); d.setDay(2023, 8, 1); d.printDate(); } }
🍩在今后写代码中尽量都用 this
4.3 this引用的特性
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
- this只能在"成员方法"中使用
- 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
- this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收
5. 对象的构造级及初始化
5.1 如何初始化对象
在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
比如:
public static void main(String[] args) { int a; System.out.println(a); }
编译器就会提示你,使用了未初始化的变量 a:
要让上述代码通过编译,非常简单,只需在正式使用 a 之前,给 a 设置一个初始值即可。
如果是对象:
public class Date { public int year; public int month; public int day; public void setDay(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public void printDate() { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date d = new Date(); d.printDate(); d.setDay(2023,8,1);//初始化具体日期 d.printDate(); } }
🍤 运行结果:
通过上述例子发现两个问题:
- 每次对象创建好后调用 SetDay 方法设置具体日期,比较麻烦,那对象该如何初始化?
- 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
5.2 构造方法
5.2.1 概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
例如:
public class Date { public int year; public int month; public int day; // 构造方法: // 名字与类名相同,没有返回值类型,设置为void也不行 // 一般情况下使用public修饰 // 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次 public Date(int year, int month, int day){ this.year = year; this.month = month; this.day = day; System.out.println("Date(int,int,int)方法被调用了"); } public void printDate(){ System.out.println(year + "-" + month + "-" + day); } public static void main(String[] args) { // 此处创建了一个Date类型的对象,并没有显式调用构造方法 Date d = new Date(2023,8,1); // 输出Date(int,int,int)方法被调用了 d.printDate(); // 2023-8-1 } }
🍩构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。