☰
继承与super关键字
2026/11/3 10:37:54 网站建设 项目流程

继承的思想与extends关键字

继承是指对每个类的共性进行抽取,好处是可以达到代码的复用。我们看这两个类

public class Dog { String name; int age; public void eat(){ System.out.println(this.name+"正在吃饭"); } public void shout(){ System.out.println(this.name+"正在汪汪叫"); } } public class Cat { String name; int age; public void eat(){ System.out.println(this.name+"正在吃饭"); } public void mimi(){ System.out.println(this.name+"正在喵喵叫"); } }

可以看到,Dog类和Cat都有重复的代码,那么我们就可以对它们的共性进行抽取为一个新的类Animal,这就是继承的思想。

public class Animal{ String name; int age; public void eat(){ System.out.println(this.name+"正在吃饭"); } }

我们将Animal类称之为父类、基类或超类,将Dog类和Cat类称之为子类或派生类,子类继承父类的成员变量和方法。所以通过子类就可以访问父类被public和protected修饰的成员变量和方法(default修饰的只允许同包子类访问,private修饰的子类不可以访问)

public class Animal { String name; int age; public void eat(){ System.out.println(this.name+"正在吃饭"); } } public class Dog extends Animal{ public void shout(){ System.out.println(this.name+"正在汪汪叫"); } } public class Cat extends Animal{ public void mimi(){ System.out.println(this.name+"正在喵喵叫"); } }

可以看到,继承需要使用关键字extends,子类extends父类

public class Main { public static void main(String[] args) { Dog dog=new Dog(); Cat cat=new Cat(); //子类直接调用父类成员变量和方法 dog.name="旺财"; dog.age=5; dog.eat(); //子类调用自己的方法 dog.shout(); System.out.println(dog.name); System.out.println(dog.age); } }

子类父类同名成员和super关键字

同名成员变量的访问

那么如果子类和父类出现同名的成员变量呢?

结论:就近原则,优先访问自己的,自己没有再访问父类的。

public class Base { int a=1; int c; } public class Derieved extends Base{ int a=11; int b; public void func(){ System.out.println(this.a); } } public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); derieved.func(); } }

可以看到,最终输出的是子类的a值

但父类的a变量我们该怎么访问呢?这时我们可以利用super进行访问

public class Derieved extends Base{ int a=11; int b; public void func(){ System.out.println("子类a:"+this.a); System.out.println("父类a:"+super.a); } }

总结:this既可以访问父类又可以访问子类,当父类子类成员变量同名时,只访问子类。

super用来访问父类成员变量

同名成员方法的访问

如果子类和父类出现同名的成员方法呢?

public class Base { int a=1; int c; public void test() { System.out.println("Base:test()"); } } public class Derieved extends Base{ int a=11; int b; public void test() { System.out.println("Derived:test()"); } }

我们在父类和子类中定义名字参数返回值完全相同的方法,此时子类对象是会调用父类还是子类方法呢?

public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); derieved.test(); } }

可见,依旧遵循就近原则,优先调用子类自己的方法。我们将在子类中定义与父类返回类型,名字,参数列表都一样的方法称为方法的重写,那么父类方法被重写后就无法调用了吗?不是的,和先前的同名成员变量一样,我们依旧可以在子类中使用super关键字调用父类方法。

public class Base { int a=1; int c; public void test() { System.out.println("Base:test()"); } } public class Derieved extends Base { int a = 11; int b; public void test() { System.out.println("Derived:test()"); } public void func() { this.test();//this调用子类自己的test() super.test();//super调用父类的test() } } public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); derieved.func(); } }

如果我们在父类和子类中定义名字相同但参数不同的方法,此时就构成了方法的重载,所以理所应当会根据参数选择合适的方法调用

public class Base { int a=1; int c; public void test()//没有参数 { System.out.println("Base:test()"); } } public class Derieved extends Base{ int a=11; int b; //有形参 public void test(int A) { System.out.println("Derived:test()"); } public void func(){ System.out.println("子类a:"+this.a); System.out.println("父类a:"+super.a); } }
public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); derieved.test();//无参调用 } }

无参调的是父类方法:

public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); derieved.test(2);//传参 } }

有参调的是子类方法:

总结

1.父类与子类的成员变量同名时,子类/this优先调用自己的变量

2.父类与子类的方法同名时,若为重写,则子类/this也优先调用自己的方法;若为重载,则子类/this根据参数列表选择调用

3.super关键字可以用来调用父类成员,但注意只能在子类非静态方法中使用,因为静态方法是不依赖于对象的,而super和this都依赖于对象。

super关键字在构造方法中的应用

该关键字的重要作用就是在子类中访问父类成员,它在子类和父类的构造方法中产生巨大作用。

(super只能访问当前子类的父类,不能访问父类的父类)

当子类继承父类后,子类需要先帮助父类初始化。

public class Base { public Base(){ System.out.println("父类构造方法"); } } public class Derieved extends Base { public Derieved(){ //子类在这里用super()默认调用了父类的构造方法,先帮父类初始化 System.out.println("子类构造方法"); } } public class Main { public static void main(String[] args) { Derieved derieved=new Derieved(); } }

如果父类显示定义无参或默认构造方法,在子类构造方法的第一行就会默认调用super(),即调用父类构造方法。

但当父类一旦显示定义有参构造方法,那么编译器就不会默认调用父类构造方法,需要自己手动调用super,并且super一定要在第一行:

public class Base { int m; int n; public Base(int m,int n){ this.m=m; this.n=n; System.out.println("父类构造方法"); } } public class Derieved extends Base { int a ; int b; public Derieved(int a,int b,int m,int n){ super(m,n);//super在第一行,显示调用父类含参构造方法 this.a=a; this.b=b; System.out.println("子类构造方法"); } }

因为this()也要在第一行,所以显然super()和this()不可共存在一个函数中。

当你没有写任何构造方法是java会提供目前屏蔽起来的代码,但当你自己写了的时候,java就不会自动给你提供

public class Base { // Base(){ // } } public class Derieved extends Base { // Derieved(){ // super(); // } }

总结

1.super关键字用于访问当前子类的父类

2.先有父后有子,子类构造时必须先调用父类构造方法,编译器会默认super()调用父类默认构造函数或无参构造,但是当父类一旦显示为有参构造,那么就需要我们手动显示地添加super(参数1,参数2)

3.super()必须放在子类构造函数的第一条语句,super()和this()不可共存

super和this的区别

相同点:

1.都是java关键字

2.只能在非静态方法中使用,用来访问非静态成员方法和字段,依赖于对象

3.在构造方法中调用时,必须时构造方法中的第一条语句,并且不能同时存在

不同点:

1.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用。

2.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。

3.在构造方法中:this(...)用于调用本类构造方法,super(...)用来调用父类构造方法,两种调用不能同时在构造方法中出现

4.构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询