类与对象中成员变量初始化(默认-显式-针对性)和this关键字

初始化

今天在讲构造函数与成员函数的区别之前,我们先提出一个成员变量初始化的问题,因为在面向对象中,构造函数有它特殊的意义,我们创建对象时,成员变量的数值是怎样变化的呢?

  • 默认初始化
public class CarTest{
	public static void main(String[] args){
		Car c = new Car();//创建对象并将地址赋给变量c
		c.run();//对象的引用c调用run();
	}
}
class Car{
	String brand;//成员变量 品牌
	char color;//成员变量 颜色
	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

如果运行 CarTest ,就会出现该结果:品牌:null 颜色:0
所以,当我们对象创建时,成员变量会默认初始化。
String 默认 null
int 默认 0
double 默认 0.0
char 默认 0
boolean 默认 false

  • 显式初始化
public class CarTest{
	public static void main(String[] args){
		Car c1 = new Car();//创建对象并将地址赋给变量c1
		c1.run();//对象的引用c1调用函数run();
		Car c2 = new Car();//创建对象并将地址赋给变量c2
		c2.run();//对象的引用c2调用函数run();
		Car c3 = new Car();//创建对象并将地址赋给变量c3
		c3.brand="BYD";//将"BYD"赋给成员变量brand
		c3.run();//c3再次调用run()
	}
}
class Car{
	String brand="BMW";//成员变量 品牌=BMW
	char color='b';//成员变量 颜色=b
	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

上述成员变量没有添加权限,一般会加private,这里对该问题先不注重!
运行 CarTest ,就会出现该结果:

  • 品牌:BMW 颜色:b
  • 品牌:BMW 颜色:b
  • 品牌:BYD 颜色:b

上述三种结果,如果我们不去修改成员变量的值,那么它显示的结果就是我们Car类中成员变量一开始就赋的初始值“BMW”和‘b’,但是他们都会先经过默认初始化,从无到有,然后进行显式初始化,才会有“BMW”和‘b’的结果。
c1,c2 的结果是创建对象过程时,把值给了c1,c2;c3是创建时先进行了默认初始化,又进行了显式初始化,当时值为“BMW”和‘b’,创建完后最终又将“brand”的值改为BYD,经过了从无到有到更改,那么我们想直接创建一个BYD的品牌,那么就提出第三种初始化,针对性初始化。

  • 针对性初始化
    我们在文章的开头提到了构造函数有特殊意义,那么在这里它的意义就是针对性初始化,首先我们来了解构造函数的格式:
//构造函数格式
权限修饰符 类名(参数列表){
	return;//默认存在,仅仅代表结束函数
}
  • 注意:无参的构造函数默认存在,如果类中定义了其他有参的构造函数,无参的构造函数就不存在,建议一般直接将无参的写在第一个。

可以看出来,构造函数和成员函数的第一个区别是:构造函数不需要返回值类型,而成员函数可需可不需。
我们继续讨论针对性初始化:

public class CarTest{
	public static void main(String[] args){
		Car c1 = new Car();//创建对象并调用无参构造函数Car()
		c1.run();
		Car c2 = new Car("Audi");//创建对象并调用构造函数Car(String brand)
		c2.run();
		Car c3 = new Car("Ferrari",'r');//创建对象并调用构造函数Car(String brand,char color)
		c3.run();
	}
}
class Car{
	String brand="BMW";//成员变量 品牌=BMW
	char color='b';//成员变量 颜色=b
	public Car(){}
	public Car(String brand){
		this.brand=brand;
	}
	public Car(String brand,char color){
		this.brand=brand;
		this.color=color;
	}
	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

运行 CarTest ,出现该结果:

  • 品牌:BMW 颜色:b
  • 品牌:Audi 颜色:b
  • 品牌:Ferrari 颜色:r

在该代码中这个就是针对性初始化,但是它的结果经历是:

  • 创建对象时,成员变量brand和color默认初始化分别为null和0;
  • 如果有了初始值,就在创建对象时,当调用构造函数进栈时,再进行显式初始化;
  • 当调用的是有参数的构造函数,进行具体代码功能,将传入的局部变量赋值给当前对象的成员变量,称为针对性初始化。

this关键字

在我们说到初始化的问题时,我们代码中写了this关键字, 如:

public class CarTest{
	public static void main(String[] args){
		Car c2 = new Car("Audi");//创建对象并调用构造函数Car(String brand)
		c2.run();
	}
}
class Car{
	String brand="BMW";//成员变量 品牌=BMW
	char color='b';//成员变量 颜色=b
	public Car(){}
	public Car(String brand){
		this.brand=brand;
	}
	public Car(String brand,char color){
		this.brand=brand;
		this.color=color;
	}
	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

上述分别为无参,有一个参数,有两个参数的构造函数,他们之中有this关键字,如:this.brand=brand;左边的this指的是当前对象的引用,存放当前对象的地址,因为在创建对象的同时,调用构造函数,所以this就是指创建出来的对象,如Car c2 = new Car(“Audi”);this就是指的c2,他在构造函数的空间里相当于一个变量,里面存放这c2的地址(c2是对象的引用存放对象地址),调用的是一个参数的构造函数Car(String brand),“Audi”是该构造函数的局部变量brand的值,this.brand=brand;就是将局部变量brand传入的值“Audi”赋值给当前对象c2的成员变量brand。
我们画图演示一下:
在这里插入图片描述
所以,当下面的成员函数被调用执行后,输出的结果就是调用的对象c2中的成员变量 brand=Audi 和 color=0;

	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
  • this第一个用处就是本身表示当前对象的引用

this()

  • 上述我们说到this本身是对当前对象的引用,还有一个作用就是this(参数列表)表示调用当前类中其他的构造函数,通过以下代码证明:
class Car{
	String brand;//成员变量 品牌
	char color;//成员变量 颜色
	public Car(){
		//Car(null,0);
		this(null,0);
	}
	public Car(String brand){
		//Car(brand,0);
		this(brand,0);
	}
	public Car(char color){
		//Car(null,color);
		this(null,color);
	}
	public Car(String brand,char color){
		this.brand=brand;
		this.color=color;
	}
	public void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

对比上面的代码,我们可以看到,一个参数的构造函数里面有调用的是两个参数的构造函数,不过构造函数如果只有一个参数,另一个参数在调用两个参数的时候传入的参数为默认值:如 this(brand,0) 和 this(brand,0)

  • this(参数列表)必须放在第一句,否则会覆盖。
public class CarTest{
	public static void main(String[] args){
		Car c1 = new Car("Audi");
	}
}
class Car{
	String brand;//成员变量 品牌
	char color;//成员变量 颜色
	public Car(){
		//Car(null,0);
		this(null,'0');
	}
	public Car(String brand){
		//Car(brand,0);        
		brand="BMW";//看这里!!!
		this(brand,'0');
	}
	public Car(char color){
		//Car(null,color);
		this(null,color);
	}
	public Car(String brand,char color){
		this.brand=brand;
		this.color=color;
	}
	p ublic void run(){
		System.out.println("品牌:"+brand+" 颜色:"+color);
	}
}

当我们编译这段代码时,会报以下错误:
在这里插入图片描述

假设先忽略这个要放在第一句的错误,brand=“BMW”;this(brand,‘0’);执行成功,但是我们调用时 new Car(“Audi”) ,传入的是 (“Audi” ),结果会显示 Audi,"BMW"会被覆盖,所以要将this(参数列表)放在第一句。

OK!这个就是成员变量初始化和this关键字的东西,下一篇我打算是沿着this这个思路,讲构造函数和成员函数的区别,以及他们之间的调用。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值