来都来了,浅浅的给个赞呗!!!
目录
一,super调用构造器五个注意点:
浅谈java super函数的相关概念:
首先,要说super();这个函数,我们就要提到java中的类的继承了,而说到类的继承这个事,我们就会提到子父类这个概念,子父类就是一个类继承了另一个类,我们管被继承的这个类叫父类或者超类,主动去继承的这个类我们叫子类,或者基类,就好比儿子和爸爸一样,儿子总会继承一些爸爸的基因,比如眼睛像什么的,子类也会继承父类的部分特点,比如父类的属性(非私有)、方法(非私有),那么什么又是继承呢?就是父类中定义的属性、方法,我们可以在子类中通过父类的对象去调用,然而在子类继承父类的时候是不能继承父类的构造函数的,但是我么可以在子类的构造函数中调用父类的构造函数;调用时我们就会用到super()函数了。
浅谈java构造函数相关问题
而如果在一个类中我们没有去手动定义一个或多个构造函数时,系统会默认的给你提供一个无参、无返回值的构造函数,
在子类继承父类后,再给出子类的构造函数后,其实就已经在子类构造函数中隐式调用了super()函数,什么是隐式呢,就是被隐藏了。为什么隐藏呢?下面黄色字体内容就是原因。(即子类的构造函数中默认调用父类的无参构造函数,只不过第一行代码:super()一直被省略了)。
(这里省略的原因是为了保证super();一直在子类构造函数的首行,那为什么要在第一行呢?因为这个是java的规定)
如果子类的某个构造函数想要调用父类的其他带参构造函数,在构造函数第一行添加super(参数名1,参数名2,等等);(参数的多少根据想调用父类构造函数的形参而定)
调用父类的构造函数要放在子类的构造函数体中的第一行super(参数名1,参数名2,等等);
注意这里:子类调用父类的含参构造函数时,传递参数时没有参数类型,只有参数名。
//正确调用
super(age,name);
//错误调用
super(int age,String name);
调用了父类的其他有参构造函数,那么子类的该构造函数不会再调用父类的默认无参构造函数了,也就是说子类只能调用父类的一个构造方法。
关于子父类构造函数相关知识点:
一,super调用构造器五个注意点:
- 我们可以在子类的构造器中显式的使用"super(形参列表)”的方式,调用父类中声明的指定的构造器,(其实你不写也可以,系统会默认隐式给你)
- "super(形参列表)"的使用,必须声明在子类构造器的首行!可以显式可以隐式。
- 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
- 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造
- 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
二,为什么子类会调用父类的构造函数呢?
- 首先我们要知道构造方法是类的一个特殊成员,它会在类实例化对象时被自动调用
- 为什么子类的构造函数中要去调用父类中的构造函数呢?因为子类继承父类,会继承到父类中的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类在进行对象初始化时,先调用父类的构造函数,这也是子类的实例化过程
- 父类中存在无参构造函数,是子类存在构造函数的前提,如果父类中不存在无参构造器(由于类会默认存在一个无参构造器,此时的情况指的是父类存在有参构造器而没有显式的写出无参构造器),子类中只要存在构造器就会报错(子类默认存在的无参构造器也会报错哦)。
- 父类存在无参构造器且有有参构造器时,子类可以只存在有参构造,在调用子类有参构造器时,会先调用父类的无参构造器。
- 子类在实例化对象时,根据参数列表选择合适的构造函数进行初始化,子类的任何构造器被调用时都要先调用父类的无参构造函数(因为这是前提)
总结:如果存在类的继承关系:那么要想给子类添加构造函数,他的父类就必须含有无参构造函数,为什么呢?因为子类的构造函数的首行都默认隐式的调用了父类的无参构造函数,那父类都没有,你子类还调用,那坑定会报错;
三,我们会在哪里调用父类的构造函数呢?
我们可以在子类的方法或构造器中。通过使用"super.属性”或”super.方法”的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性”的方式,表明调用的是父类中声明的属性。
特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法”的方式,表明调用的是父类中被重写的方法。
代码示例:
示例:父类
public class GeometricObject {
private String color;
private double weight;
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public GeometricObject(){
super();
this.setColor("white");
this.setWeight(1.0);
}
public GeometricObject(String color,double weight){
super();
this.color=color;
this.weight=weight;
}
}
子类:
public class Circle extends GeometricObject{
private double radius;
public Circle(){
super();
this.radius=1.0;
// this.setColor("white");
// this.setWeight(1.0);
因为父类中的构造方法中已经有this.~~就不用再重复写了,没有意义。
}
public Circle(double radius){
super();
this.radius=radius;
// this.setColor("white");
// this.setWeight(1.0);
因为父类中的构造方法中已经有this.~~就不用再重复写了,没有意义。
}
public Circle(double radius,double weight,String color){
// super();
// this.radius=radius;
因为父类中的构造方法中已经有this.~~就不用再重复写了,没有意义。
// this.setWeight(weight);
// this.setColor(color);
父类中有这两个参数的构造方法,直接就可以调用。
// super(String color,double weight);错误的调用格式;
super( color,weight);//正确调用格式;
this.radius=radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}