super和this在子类,内部类,实现类,子接口中的使用区别
一、super和this在子类中的使用
当一个子类继承一个父类时,我们在子类的构造器中通过super()来调用其父类的构造器。
public class FatherClass {
FatherClass(){
}
}
class SonClass extends FatherClass{
SonClass(){
super();
}
}
以上是一个最简单的super()的用法,其中如果我们在子类的构造器中省略super(),那么编译器会自动为子类的构造器中添加一个super()在第一行。(当父类有无参构造器时我们才可以省略)
super()仅能在子类构造器中调用,且只能调用一次。
此外,我们可以通过super.或者this.的方式来调用父类的变量或父类的方法以及当前子类的变量或当前子类的方法。
这个设计的目的是为了解决某些时候类的变量或方法可能被覆盖。
例如:
public class FatherClass {
int i = 10;
FatherClass(){
}
FatherClass(int i){
this.i = i;
}
public void show() {
System.out.println(this.i);
}
}
class SonClass extends FatherClass{
int i = 5;
public void show() {
System.out.println(super.i+"\n"+this.i+"\n"+i);
}
}
显然,子类定义int i = 5会覆盖父类的i,如果我们不使用super或this,那么所有的i都将指向当前子类的i。
但通过super.i我们将可以调用父类的i。
同时,在父类的有参构造器中我们可以看到,如果形参名和类的变量名重复,那么形参将会覆盖类的变量。
但我们可以通过this.i的方法来指向类的变量i而非形参i。
其次,我们可以通过当前子类.super.i或当前子类.this.i的方式来分别调用父类的i或者子类的i。
这一方式和直接使用super.i与this.i是等同的。
我们无法通过父类.super或父类.this的方式来调用父类的父类或父类。
二、super和this在内部类中的使用
对于内部类而言,super()和this的用法基本一致。
并且我们可以通过外部类.super和外部类.this的方法来调用外部类的父类和外部类。
(外部类和内部类的具体定义在此不详细描述)
public class FatherClass {
int i = 10;
public void show() {
System.out.println(i);
}
}
class SonClass extends FatherClass{
int i = 9;
class InnerClass{
int i = 8;
public void show() {
System.out.println(SonClass.super.i);
System.out.println(SonClass.this.i);
System.out.println(this.i);
}
}
public void show() {
System.out.println(super.i+"\n"+this.i+"\n"+i);
}
}
class GrandsonClass extends SonClass{
class InnerClass extends SonClass.InnerClass{
public void show() {
System.out.println(super.i);
}
}
}
三、super和this在实现类中的使用
当我们直接在实现类中使用super和this,以及当前类名.super和当前类名.this和一、二是一样的。
但特殊的是,我们可以使用父接口.super的方式来调用父接口中的方法或变量。
(父接口.this的使用方法是错误的,不成立的行为)
有些人会问,为什么需要调用父接口中的方法或变量。
首先,父接口中的变量我们知道一定是static final修饰的一个public变量,那么我们可以直接通过父接口.变量名的方式来调用,和父接口.super.变量名的调用方式是等同的。
但是final修饰的常量变量是不能被继承的,所以即便实现类中没有对该变量进行覆盖,我们仍然无法对其进行直接调用。
其次,父接口中的方法可以被调用的前提显然是父接口中的方法被实现。
而接口中能够实现方法的形式只有两种,1.default修饰的方法(详细内容可见笔记四)2.static final修饰的方法。
对于第二种情况和调用接口变量是等同的,就不再赘述。
但第一种情况如果我们覆盖了该方法,在其他情况下想要调用未重写的该方法,我们必须通过父接口.方法名的方式来调用。
四、super和this在子接口中的使用
由于接口不是类,super和this的使用和类将会产生较大的区别。
首先我们无法在子接口中使用super,只能使用this。(接口名.super和接口名.this仍旧等价于super和this)
而对于父接口,我们无法通过super来调用的情况下,我们必须通过父接口名.super的方式来调用某个父接口。
也就是说父接口名.super指向的不是父接口的父接口,而是其本身。
这是因为一个接口可以继承多个接口,我们无法直接使用super来指代某一个父接口,所以编译器阻止了super这样的用法,即便只继承了一个父接口,改而使用父接口名.super这样显式的指出哪一个父接口。
五、特殊注意事项
尽管接口不是类,但我们仍然可以调用接口的getClass方法。
但是接口的getClass方法得到的class是其实现类。
本文地址:https://blog.csdn.net/qq_36988636/article/details/107455282