this引用的介绍
在上一篇的类与对象的介绍中,我们了解了什么是对象,什么是类,类就是对一个实际存在的事物的描述,类实例化出来的东西我们称为对象。那么今天我们介绍的这个关键字this他的作用是什么呢?我们先来看一段代码:
public class Person {
public String name;
public int age;
public void setDate(String n,int a) {
name = n;
age = a;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
首先我们创建一个人类,类里面有两个成员变量为名字和年龄,有两个方法setDate show
用来给成员变量赋值和打印成员变量。
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.setDate("张三",18);
p.show();
Person p2 = new Person();
p.setDate("李四",20);
p.show();
}
}
现在我们使用new关键字,实例化了两个Person类的对象,p和p2,我们通过对象调用成员方法,进行赋值和打印
但是我们有一个疑问了,我们实例化了两个对象,两个对象都在调用show setDate
方法,我们没有给出任何说明,show setDate
怎么知道打印的是那个对象的数据呢?其实每个成员方法都有一个隐藏的参数DateUtil this
,这个this引用指向了当前对象(这个对象是成员方法运行时,调用该成员方法的对象)。
我们再来看一个例子:
public class Person {
public String name;
public int age;
public void setDate(String name,int age) {
name = name;
age = age;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
我们看setDate
这个成员方法,我们将参数不小心写的与成员变量名字相同了。这时候还可以正常给成员变量赋值嘛?
我们看并没有打印我们赋值的数据,这是为什么呢?
如何解决这个问题呢?我们就可以使用我们的this引用。
public class Person {
public String name;
public int age;
public void setDate(String name,int age) {
this.name = name;
this.age = age;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
这样我们就可以给成员变量赋值了,因为我们上面说过了,this是一个引用,他指向了调用该成员方法的对象,所以我们通过这个this引用去访问成员变量时,访问的就是调用该方法的对象的成员变量,就可以区分出成员变量和形参,完成我们的赋值。
this引用总结
好了经过上面的介绍我们可以对this进行一个简单的总结:
1、this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
2、this只能在成员方法中使用
3、在成员方法中,this只能引用当前对象,不能在引用其他对象。
构造方法
在之前的学习中我们肯定知道,一个局部变量在使用时必须初始化,如果不进行初始化,编译时就会报错。那么这个变量如果是成员变量呢?在上面的例子当中我们写了这样一个代码:
public class Person {
public String name;
public int age;
public void setDate(String name,int age) {
this.name = name;
this.age = age;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.show();
p.setDate("张三",19);
p.show();
}
}
我们创建了一个人类,并且实例化了一个对象p
,实例化后我们直接调用show
方法来打印成员变量,通过对象调用setDate
成员方法为成员变量赋值后再次打印,我们来看看你我们的执行结果。
通过这个例子我们会有两个疑问:
1、每次实例化对象后,需要调用setDate方法才可以给成员变量赋值,太麻烦,可不可以在实例化对象时直接赋值呢?
2、局部变量必须初始化才能使用,但成员变量我们在实例化对象后可以直接打印,这是为什么呢?
首先我们来回答第一个问题,我们可以在实例化对象的时候给成员变量赋值,需要调用我们的构造方法。什么是我们的构造方法呢?构造方法没有返回值,方法名和类名是一样的
public class Person {
public String name;
public int age;
public Person () {//无参的构造方法
}
public void setDate(String name,int age) {
this.name = name;
this.age = age;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
public Person
就是Person
类里的无参构造方法,注意:当我们没有写任何构造方法的时候,Java会帮助我们提供一个默认的无参的构造方法。有的兄弟就会问了你这无参的构造方法有啥用,也不能实现我在实例化时就给成员变量赋值的需求啊,各位稍安勿躁,既然有无参的构造方法,那么就肯定有有参的构造方法。
public class Person {
public String name;
public int age;
public Person () {//无参的构造方法
}
public Person(String name,int age ) {//有参的构造方法
this.name = name;
this.age = age;
}
public void setDate(String name,int age) {
this.name = name;
this.age = age;
}
public void show (){
System.out.println("name " + name + " age " + age);
}
}
public Person(String name,int age )
这样我们就创建了一个有参的构造方法,在我们实例化对象时就可以给成员变量赋值了。
public static void main(String[] args) {
Person p = new Person("张三",20);
p.show();
}
有的同学又会问了:你怎么证明 当我们没有写任何构造方法的时候,Java会帮助我们提供一个默认的无参的构造方法。我们来看当我们写了一个有参的构造方法之后,在实例化对象时我们不进行赋值会发生什么?
因为我们没写无参构造方法且自己写了有参的构造方法,Java不会提供无参的构造方法了,所以我们的程序就会报错了,自己写一个无参构造方法后解决了问题。其实我们仔细观察一下,有参与无参的构造方法是什么?是不是就是重载,他们的方法名相同,参数不同,构造方法也是可以互相调用的,使用this()
就可以实现。这样我们的第一个问题就解决了。
下面我们来看第二个问题,为什么成员变量可以不用赋值直接打印?答案是在实例化对象中,我们为对象分配内存空间之后,会初始化所分配的空间,即对象空间被申请好之后,对象中包含的成员已经设置好了初始值。
类型 | 默认值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0 |
char | /u0000 |
boolean | false |
reference | null |
在这之后我们会调用构造方法,给对象中各个成员赋值。
构造方法总结
构造方法的特性:
1、名字必须跟类名相同
2、没有返回值类型,不可以写void
3、创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(可以类比于一个人只出生一次)
4、构造方法可以重载,比如有参构造方法,无参构造方法
5、没有写构造方法时Java会默认提供一个无参的构造方法,但当写了任何构造方法时,Java不会给你提供无参构造方法了