五分钟“手撕”This引用、构造方法

目录

一、this引用

1.为什么会有this引用,它可以来干嘛?

2.this引用是什么

3.this引用怎么用?

二、对象的初始化及构造

 1.什么是初始化

2.如何初始化对象

3.构造方法 

3.1.什么是构造方法

3.2.什么是重载呢? 

 三、默认初始化


一、this引用

1.为什么会有this引用,它可以来干嘛?

先让我们看一个Data的例子:

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(2020,9,15);
    d2.setDay(2020,9,16);
    d3.setDay(2020,9,17);

// 打印日期中的内容
    d1.printDate();//打印结果:2020/9/15
    d2.printDate();//打印结果:2020/9/16
    d3.printDate();//打印结果:2020/9/17

}
}

以上定义了一个Data类,如何创建三个对象,传值,打印。 代码整体逻辑非常简单,没有任何问题。但是你仔细思考,如果出现下面的情况呢:

形参名不小心与成员变量名相同:

public void setDay(int year, int month, int day){
    year = year;
    month = month;
    day = day;
}

那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?估计 自己都搞不清楚了。这时候就需要this引用来解决这个问题。 

2.this引用是什么

this引用指向当前的对象,可以通过this对这个方法(形参变量什么的)里面的东西进行操作。可以类似于C语言的指针,指向这个对象,通过地址来修改里面的内容。

3.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.month = month;
    this.day = day;
}

public void printDate(){
    System.out.println(this.year + "/" + this.month + "/" + this.day);
}

}

用法:this.成员变量,输出时也需要使用this.

注意:this引用的是调用成员方法的对象。也就是说在下面的代码中,我通过使用d的方法,调用的是d这个对象,可以理解为this里面存着的是d的地址,这样可以精准的找到d这个对象然后去修改里面的内容。

二、对象的初始化及构造

 1.什么是初始化

int a;是创建一个变量,而int a=0;就是初始化变量,在创建它的时候顺便给它赋了个值,着就是初始化。

public static void main(String[] args) {
    int a;
    System.out.println(a);
}

// Error:(26, 28) java: 可能尚未初始化变量a

看上面这个代码,如果不初始化,在后续去输出它肯定会报错,为什么?

因为它只管分配空间不包括给值,里面本来就没值,你还去打印它,所以会报错! 

2.如何初始化对象

但是对于对象来说,就不会报错,我们看下面的代码:

public static void main(String[] args) {
    Date d = new Date();

    d.printDate();
    d.setDate(2021,6,9);
    d.printDate();

}
// 代码可以正常通过编译

那我们可以得到两个问题:

1.为什么a会报错,而上面的代码不会报错呢?

2.并且每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象该如何初始化?

那么这时候我们的构造方法就出现了,让我们一起往下看: 

3.构造方法 

3.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(2021,6,9); // 输出Date(int,int,int)方法被调用了
    d.printDate(); // 2021-6-9
}

}

注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。 

 注意事项:1. 名字必须与类名相同

2. 没有返回值类型,设置为void也不行

3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)

4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)

public class Date {
    public int year;
    public int month;
    public int day;

// 无参构造方法
public Date(){
    this.year = 1900;
    this.month = 1;
    this.day = 1;
}

// 带有三个参数的构造方法
public Date(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
}

public void printDate(){
    System.out.println(year + "-" + month + "-" + day);
}

public static void main(String[] args) {
    Date d = new Date();
    d.printDate();//打印1900-1-1
}

}

但是当你自己写出了一个构造方法的话,编译器就不会再给你提供。(简单来说:救急不救穷,你没有我就给你,有了就不给) 

public class Date {
    public int year;
    public int month;
    public int day;

public Date(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
}

public void printDate(){
    System.out.println(year + "-" + month + "-" + day);
}

public static void main(String[] args) {
// 如果编译器会生成,则生成的构造方法一定是无参的
// 则此处创建对象是可以通过编译的
// 但实际情况是:编译期报错
    Date d = new Date();
    d.printDate();
}

}
/*
Error:(26, 18) java: 无法将类 extend01.Date中的构造器 Date应用到给定类型;
需要: int,int,int
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
*/

构造方法中,可以通过this调用其他构造方法来简化代码 

public class Date {
    public int year;
    public int month;
    public int day;

// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(1900,1,1);必须是构造方法中第一条语句
public Date(){
//System.out.println(year); 注释取消掉,编译会失败
    this(1900, 1, 1);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
}

// 带有三个参数的构造方法
public Date(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
}

}
3.2.什么是重载呢? 

上述代码中,两个Data构造方法:名字相同,参数列表不同,因此构成了方法重载。 

 三、默认初始化

在上文中提出的第一个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢? 

public class Date {
    public int year;
    public int month;
    public int day;

public Date(int year, int month, int day) {
// 成员变量在定义时,并没有给初始值, 为什么就可以使用呢?
    System.out.println(this.year);
    System.out.println(this.month);
    System.out.println(this.day);
}

public static void main(String[] args) {
// 此处a没有初始化,编译时报错:
// Error:(24, 28) java: 可能尚未初始化变量a
// int a;
// System.out.println(a);
    Date d = new Date(2021,6,9);
}

}

要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情: 

Date d = new Date(2021,6,9);

 在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:

1. 检测对象对应的类是否加载了,如果没有加载则加载

2. 为对象分配内存空间

3. 处理并发安全问题 比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突

4. 初始化所分配的空间 即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:

5. 设置对象头信息

6. 调用构造方法,给对象中各个成员赋值 

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值