java构造器与继承
目前看书正在学习java,怕好记性比不过烂笔头,遇到的一些东西还是记录一下比较好,方便日后查阅。
-
谁能有构造器
抽象类,普通类都可以用构造器,如果用户没有自定义一个构造器,那么编译器就会自动创建个啥也不做的构造器。如果用户定义了构造器,编译器就会把定义构造器的任务交给你,不会创建默认构造器。
-
构造器重载
编译器默认创建的构造器是无参数的,用户可以自己定义重载构造器。一个类不能有两个或以上相同的构造器,即参数列表不能够相同。
-
构造器调用
在类的声明时候就可以调用构造器,在方法内也可以调用构造器。抽象类不能够单独实例化,构造函数必须要跟在new关键字的后面才可以成功编译,但是特殊情况在于可以在构造函数里调用构造函数。比如以下代码
public class Duck{
int size;
public Duck(){
this(0);
}
public Duck(int newSize){
if (newSize == 0){
size = 27;
} else {
size = newSize;
}
}
public static void main(String[] args){
Duck duck = new Duck();
System.out.println(duck.size);
}
}
构造器里调用构造器需要使用this关键字
-
当有继承关系的子类开始实例化
-
构造器调用顺序
如果有父类,那么先调用父类的构造器,如果父类还有父类,那么调用父类的父类的构造器,以此类推。必须触底然后再一层一层的返回,也就是说最先完成的构造函数是最遥远的祖宗。
-
如果父类是一个抽象类
没错,抽象类也可以调用构造器为其分配空间,但要记住,抽象类的构造函数主要是给派生类实例化时使用,不能单独实例化。
abstract class A{ int a; void show(){ System.out.println(a); } abstract void doSuff(); } class B extends A{ @Override void doSuff(){ System.out.println("I will show the value of A"); show(); } public static void main(String[] args){ B b = new B(); b.doSuff(); } }因为抽象类也需要空间去储存变量,所以需要构造函数去分配空间,在这里A所分配的空间在堆上属于B的一部分。
-
如果父类有封装
如果父类的某个变量用比如private修饰,当子类继承父类时,这个变量的开销还是得要子类承担,只不过子类无法访问这个变量,但这个变量是真实存在的。
-
指定父类的构造函数
如果想要在实例化一个类时指定父类怎么实例化(默认情况下是调用父类的无参数构造函数),使用super(参数列表)就行了。
abstract class A{ public A(int x){ a = x; } int a; void show(){ System.out.println(a); } abstract void doSuff(); } class B extends A{ public B(){ super(1); } @Override void doSuff(){ System.out.println("I will show the value of A"); show(); } public static void main(String[] args){ B b = new B(); b.doSuff(); } }如果把B的构造函数去掉,那么就会报错,报错的原因是因为编译器创建的默认的B构造函数是啥也不做的,不会去指定调用父类的构造函数,而是尝试调用父类的无参数构造函数,但是A并没有无参数构造函数。
-

浙公网安备 33010602011771号