this和super,我和我爸?

相信大家已经对Java基础内容有所了解了,本篇博客为大家讲解在编程过程中两个重要的关键字thissuper,不管是已经有所了解,还是晕晕乎乎,亦或是学得不错,希望看完这篇博客后,都对你能所有帮助。
接下来进入我们的正文内容:this与super。

this与super

this关键字

this在Java中指代当前对象

this关键字的主要使用方式有两种:

1.使用this指代当前对象,并调用属性和方法

2.使用this()来指代本类构造器

使用方式一:在方法中操作当前对象属性和方法

当我们需要在方法中使用当前对象的属性和行为时,我们使用this来指代调用方法的对象本身。并用this.属性或this.方法名()的方式来调用属性和行为。

例如:在Test类中具有两个属性

1
2
public String name;
public int age;

name和age是Test类的属性,该类有一个自我介绍的方法selfIntroduction(),那我们如何在该方法中使用当前对象的属性值呢?

selfIntroduction()方法:

1
2
3
public void selfIntroduction() {
System.out.println("我叫"+this.name+"今年"+this.age);
}

在测试类中

1
2
3
4
5
6
public static void main(String[] args) {
Test t1 = new Test();
t1.name = "小明";
t1.age = 19;
t1.selfIntroduction();
}

执行结果为:输出了“我叫小明今年19”。

从上述代码中可以看出,我们使用this.name的方式调用到了当前对象的name值,同样,我们也调用到了当前对象的age值

不难发现,使用this.name的方式,获得了调用selfIntroduction()方法的当前对象的name属性值,也就是说,这个时候this对象指代的是此时调用该方法的当前对象。

这样我们就可以理解,为什么使用this.name和使用this.age可以得到”小明”和19这两个值了。

那既然this可以指代当前对象,可以使用this来调用方法吗?

1
2
3
4
5
6
7
8
//在Test类中的设置姓名的方法
public void setName(String name) {
this.name = name;
}
public void selfIntroduction() {
this.setName("小红");
System.out.println("我叫"+this.name+"今年"+this.age);
}

上述代码中,在selfIntroduction()方法第一行使用this.setName(“小红”)调用了当前对象的setName(String name)方法,并传入”小红”字符串;在setName(String name)方法中使用this.name来完成当前对象name属性值的赋值。

完成上述操作后,再次输出,结果为:“我叫小红今年19”。

这就是this指代当前对象,调用属性和行为的操作。

当然,有时this是可以省略的。

例如上述:

1
2
3
public void selfIntroduction() {
System.out.println("我叫"+name+"今年"+age);
}

这样书写同样可以得到效果。

但是:一定注意,省略this是有要求的,要求是在该方法中没有局部变量和该属性名称一致。

例如:

1
2
3
4
//在Test类中的设置姓名的方法
public void setName(String name) {
name = name;
}

如果写成这样,程序执行时,会把传入的name值赋值给了传入的name值,并不会给属性name赋值,这种操作是无意义的。

为了给属性name赋值正确的写法:

1
2
3
4
//在Test类中的设置姓名的方法
public void setName(String name) {
this.name = name;
}

使用this.name代表对象的name属性,而name则代表传入的name局部变量。

注意:this只能被使用在不被static修饰的非静态方法的方法体中。

当然,this也经常被使用在构造器,进行属性的赋值,例如:

1
2
3
4
public Test(String name,int age){
this.name = name;
this.age = age;
}

利用这种方式就可以给当前对象进行属性的赋值。

使用方式二:代表当前类中的构造器

除了上述代表当前对象并调用属性和行为以外,this()可以代表本类构造器。

例:在Test类中有一个无参构造

1
2
3
public Test() {
System.out.println("无参构造");
}

如果想在有参构造中调用无参构造,这时就可以使用this()的方式来代表本类无参构造。

1
2
3
4
public Test(String name) {
this();
this.name = name;
}

当使用上述有参构造时,就会在第一行处调用无参构造,并执行无参构造的内容。

同样如果想调用上述的有参构造,也可以使用this(name)来代表有参构造。

例:

1
2
3
4
public Test(String name,int age) {
this(name);
this.age = age;
}

这样的话,就可以进行构造方法的调用了。

当然,在使用this()代表构造器时,一定要将其放在构造方法的第一行,否则会报错。

this关键字的用法先介绍到这儿,接下来看看我们了解的super。

super关键字

super:在Java继承内容中,指代子类从父类中继承的内容。

不能操作子类的内容,能操作到父类中访问修饰符允许的属性和方法,其使用方式和this有相似之处。

使用方式一:指代继承父类中的属性和行为

相信同学们在继承中已经了解到,子类对象中不仅仅有子类独有的内容,更有从父类中继承而来的内容。

那我们如何区分是父类中继承而来的内容还是子类中独有的内容呢?

例:

父类:

1
2
3
4
5
6
7
8
//父类
public class Father {
public String name;
public int age;
public void sleep() {
System.out.println("睡觉打鼾");
}
}

子类:

1
2
3
4
5
6
7
8
9
10
//子类
public class Son extends Father{
public void sleep() {
System.out.println("儿子睡觉流口水");
}
//子类独有的方法
public void playGame() {
System.out.println("喜欢打游戏");
}
}

在上述代码中子类Son继承父类Father,并重写了父类的sleep方法

如果我们要使用到父类的属性和行为

将子类改为:

1
2
3
4
5
6
7
8
9
10
11
//子类
public class Son extends Father{
public void sleep() {
super.sleep();
System.out.println("儿子睡觉流口水");
}
//子类独有的方法
public void playGame() {
System.out.println(super.name+"喜欢打游戏");
}
}

上述代码中,使用super.sleep()的方式在子类中调用了父类中的方法,和this一样,需要写在方法中。

同样,我们也可以在方法中调用从父类中继承而来的属性name,使用super.name获得name值。

但是:有同学会发现,在playGame()方法中使用this.name和super.name效果是一样的,这是为什么呢?

原因是因为这时,子类的属性都是从父类中继承而来的,使用this和super调用属性的效果都是一样的。

注意:但如果子类发生了变化,在子类中加上一个name属性,并赋值为”小明”:

1
public String name = "小明";

由于这时父类中有一个属性名称为name,而子类中也有一个属性名称为name,这时,super.name是父类继承来的name,而this.name是子类中属性,值就不一样的。

所以:不要一味的觉得super.name和this.name相同,也不要觉得它们一定不同,得具体情况具体分析。

使用方式二:代表父类中的构造器

这一点是super关键字的重要作用。

和this一样,在构造器中可以使用super()代表调用了父类的无参构造。

例如:

1
2
//父类无参构造
public Father(){}
1
2
3
4
//子类无参构造
public Son(){
super();
}

当然,也可以使用super(参数)带参的构造器,来表示调用父类有参构造。

注意事项:如果子类没有调用父类构造器,父类也没有无参构造,子类会报错。

例:

父类:

1
2
3
4
5
6
7
8
9
10
11
12
13
//父类
public class Father {
public String name;
public int age;
public Father(String name) {
this.name = name;
}
public void sleep() {
System.out.println("父亲睡觉打鼾");
}
}

子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
//子类
public class Son extends Father{
public Son() {}
public void sleep() {
super.sleep();
System.out.println("儿子睡觉流口水");
}
//子类独有的方法
public void playGame() {
System.out.println(super.name+"喜欢打游戏");
}
}

为什么子类报错了呢?一番询问后才知道,原来子类的构造器中没有指定调用其它构造器,则会默认的去调用父类构造器,并且会调用父类的无参构造。

所以在上面的代码中,由于子类无参构造没有调用指定的其它构造器,那么会去默认调用父类无参构造,结果父类中有一个有参构造,就不会自动生成无参构造,找不到父类无参构造器,导致子类出错了。

在子类构造器中实现上是:

1
2
3
public Son() {
super();
}

当调用super()父类无参构造时可以省略不用书写。

当然有人会说,难道我子类构造器就一定得调用父类无参构造?不能调用父类其它构造器或者不调用父类构造器吗?

首选,不调用父类构造器,在内存中是加载不了父类内容的,那子类就完成不了对象的创建,所以必须调用父类构造器;

其次,并不是一定要调用父类无参构造,也可以调用父类其它构造器,但由于默认会调用到父类无参构造,为了书写规范,应该给父类加上无参构造和相应的有参构造。

注意:不光是this()指代的构造器要求写在第一行,super()指代的构造器也只能写在构造器语句的第一行哟!

归纳总结

指代对象时

一:this和super关键字都只能使用在不被static修饰的非静态方法方法体中。

二:this指代当前对象,可以在代码中调用当前对象的属性和行为。

三:super代表继承父类的内容,在子类中可以调用父类继承而来的属性和行为。

指代构造器时

一:this()指代本类无参构造,而super()代表父类无参构造。

二:this()与super()不能共存,两者只能使用一个,因为在构造器中第一行只能写一个语句。

三:子类必须调用父类构造器来加载父类内容完成继承,就算不去主动调用父类构造器,子类构造器也会默认的调用父类无参构造。所以为了格式规范,应该给父类加上无参构造。

四:调用父类无参构造super()可以不写,默认调用。

内容结束了,希望能够帮助同学们对this和super有更深入的了解。