《JAVASE系列》类和对象篇:this引用与构造方法
文章目录
前言:
本章需要掌握的知识点:
- 熟悉this引用的使用与特性
- 熟练使用构造方法初始化成员变量
- 明白this引用与构造方法的关系
- new关键字背后的执行
参考书籍:《JAVA核心卷1》
你若盛开,清风自来。
1. this引用
1.1 this引用是什么?
java编译器给每个“成员方法“增加了一个隐藏的引用类型参数,该引用参数指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。
class Date{
int year = 0;
int month = 0;
int day = 0;
public void setDay(int myyear,int mymonth,int myday){
year = myyear;
month = mymonth;
day = myday;
}
public void print(){
System.out.println(year+" "+month+" "+day+" ");
}
}
public class test {
public static void main(String[] args) {
Date date = new Date();
date.setDay(2022,3,16);
date.print();
}
}
运行结果:
如果不隐藏的话应该是这样的:
在编译器中,每一个非静态的成员方法中都有一个隐藏的引用参数。这个参数就是this引用。
1.2 this引用的作用
- 解决局部变量与成员变量的名字冲突
class Date{
int year = 0;
int month = 0;
int day = 0;
public void setDay(int myyear,int mymonth,int myday){
year = myyear;
month = mymonth;
day = myday;
}
public void print(){
System.out.println(year+" "+month+" "+day+" ");
}
}
这段代码的setday方法的形参与成员变量的名字是不同的,那如果相同呢?
public void setDay(int year,int month,int day){
year = year;
month = month;
day = day;
}
这样的代码我们就无法给成员变量year赋值,因为局部变量的优先级是高于成员变量的。this引用完美解决了这个问题。
this引用的类型是类名,也就是说this引用指向的是实例化的对象。在成员方法中用this作为成员变量的前缀,即便这个成员变量与局部变量发生了名字上的冲突,this引用的变量说明了这个变量是成员变量。
public void setDay(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
- 让编译器调用时可以区别不同对象的相同方法。
class Date{
int year;
int month;
int day;
public void setDay(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public void print(){
System.out.println(year+" "+month+" "+day+" ");
}
}
public class test {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
date1.setDay(2022,3,16);
date1.print();
date2.setDay(2022,3,17);
date2.print();
}
}
编译器如何区别两个对象的相同方法?
通过this引用,每一次调用的对象的方法,都会将这个对象的地址传给this引用,使得每个方法都能找到自己的对象地址去执行。
这样不只是setDay方法能识别去初始化哪个对象的成员变量,print方法也可以识别去打印哪个对象的数据。
1.3 this引用的特性
-
this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型。
-
this只能在"成员方法"中使用。
-
在"成员方法"中,this只能引用当前对象,不能再引用其他对象,具有final属性,什么是final属性,即这个变量被final修饰是不可以进行修改的,具有常量的属性。
-
this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法。
对象的引用传递给该成员方法,this负责来接收。 -
this引用可以调用成员变量与成员方法:
this.day; this.func();
-
为了保证this的使用,我们不可以将this初始化为空。
2. 构造方法
2.1 初始化对象
在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
public static void main(String[] args) {
int a;
System.out.println(a);
}
对象中:
-
默认初始化:在对象中可以不进行初始化,变量会被编译器赋值为对应的0值
class Date{ int year; int month; int day; public void setDay(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } public void print(){ System.out.println(year+" "+month+" "+day+" "); } }
-
就地初始化:在对象中可以直接进行初始化
class Date{ int year = 0; //就地初始化 int month = 0; int day = 0; public void setDay(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } public void print(){ System.out.println(year+" "+month+" "+day+" "); } }
-
使用构造方法初始化
class Date{ int year; int month; int day; //构造方法初始化 public Date(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public void setDay(int year, int month, int day){ this.year = year; this.month = month; this.day = day; } public void print(){ System.out.println(year+" "+month+" "+day+" "); } }
2.2 构造方法的概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
public class test {
public static void main(String[] args) {
Date date1 = new Date();
}
}
当我们初始化了一个对象时,我们其实已经调用了其构造方法了。
即便我们没有为这个类定义了构造方法,编译器也会默认为我们初始化生成一个不带参数也没有初始化功能的构造函数。
class Date{
int year;
int month;
int day;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void setDay(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
public void print(){
System.out.println(year+" "+month+" "+day+" ");
}
}
构造方法的定义:
- 构造方法名必须与类名相同,没有返回值,void也不行。
- 一般用public修饰
构造方法的调用:
2.3 构造方法的特性
-
方法名必须与类名相同且没有返回值。
-
创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次。
-
构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
编译器会根据传入的形参自动调用已经定义好的构造方法。
class Date{ int year; int month; int day; public Date(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public Date(int year, int month) { this.year = year; this.month = month; } public Date(int year) { this.year = year; } public Date() { } public void print(){ System.out.println(year+" "+month+" "+day+" "); } } public class test { public static void main(String[] args) { Date date1 = new Date(2022,3,26); Date date2 = new Date(2022,3); Date date3 = new Date(2022); Date date4 = new Date(); date1.print(); date2.print(); date3.print(); date4.print(); } }
运行结果:
-
如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的,但是一旦用户自己定义了构造方法,编译器将不会生成默认的构造方法。
3. this引用与构造方法
this可以调用构造方法,但是只能在构造方法中使用并且必须是构造方法执行的第一条语句。
class Date{
int year;
int month;
int day;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public Date() {
this(2022,3,15); //必须是该构造方法的第一条语句
}
public void print(){
System.out.println(year+" "+month+" "+day+" ");
}
}
public class test {
public static void main(String[] args) {
Date date1 = new Date();
date1.print();
}
}
运行结果:
这样即使我们调用不传参的构造方法,也能做到初始化的功能。
注意:
this引用不能闭成环
如图:
4.new关键字背后的执行
Date d = new Date(2021,6,9);
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,简单理解为以下六步:
- 检测对象对应的类是否加载了,如果没有加载则加载
- 为对象分配内存空间
- 处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 - 初始化所分配的空间
即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值。 - 设置对象头信息
- 调用构造方法,给对象中各个成员赋值
总结:
类和对象本质上不算难,但是概念多,复杂。所以学习完也需要自己进行总结。
是否能回答出以下问题:
说一下this引用
构造方法的作用以及特性
this引用与构造方法之间的关系
new关键字背后执行了什么?
感谢阅读!
与君共勉!