一、构造器的使用
构造器并非类的成员(既不是成员变量,也不是成员方法)所以子类并不能继承父类的构造器(虽然构造器可以定义为public)
1.父类构造器的调用:使用super()语句。
- super()语句如果显示调用的话,必须为子类构造器的第一条语句
- 为了能够确保所有的成员都能得到正确的初始化,在系统调用子类的构造器时,会先调用父类的构造器来初始化父类的成员,然后再初始化自己。逻辑很简单,父亲都没出生,哪来的儿子?
- 如果没有显式地使用super()调用父类的构造器,且父类中又没有声明无参的构造器,就会产生编译错误。如下:
class Ball(){
public Ball(int radius){//自己构造了一个带参的构造器
}
}
class Football extends Ball{
}
子类Football没有声明构造器,所以系统会自动为其创建一个无参的构造器,即
public Football(){
super();//子类的构造器会先调用父类的构造器,这里默认为无参的super();
//但是父类中已经自己构造了一个有参的构造器,所以就不存在无参的
//构造器,编译失败
}
正确的做法应该是自己构造一个子类构造器,并显式地调用带参的super():
class Ball(){
public Ball(int radius){//自己构造了一个带参的构造器
}
}
class Football extends Ball{
public Football(){
super(20);//显式地调用父类构造器,并给参数(因为父类的构造器带参)
}
}
二、变量
1.变量可分为
- 类中声明的变量(类的成员变量,也称为域或者全局变量)
- 方法中声明的变量(局部变量)
全局变量会自动初始化,而局部变量不会自动初始化,因此如果没有初始化就使用局部变量会报错。
2.成员变量的初始化方式
对于实例变量(即不是static变量)有三种方式:
- 在声明时直接初始化
- 使用初始化块{…….}
- 使用构造器
对于static变量只有两种方式:
- 在声明时直接初始化
- 使用静态初始化块: static {……..}
不能使用构造器初始化,因为在类加载的时候就会为静态成员变量分配空间,而构造器直到创建对象时才会被调用,这个时候为静态成员变量初始化已经太迟了
变量初始化的顺序:
- 在类加载时(第一次使用类时),为类中的静态成员变量分配内存空间,并赋予默认值
- 执行静态成员变量的初始化,(两种方式:声明时直接初始化,使用静态初始化块),两种方式谁排在前面就谁先执行。
- 创建类对象时,会在堆中为类的实例分配空间,实例变量先初始化为默认值
- 执行实例变量的初始化,(三种方式:声明时直接初始化,使用初始化块,使用构造器初始化)其中前两种方式,直接初始化和初始化块谁排在前面就先执行,而构造器初始化一定排在最后
- 执行构造器初始化
3.类的加载
只有在使用到类的时候,类才会加载,如下为几种情况:
- 第一次new一个实例对象出来
- 第一次使用了类的静态成员变量(还没有生成实例对象)
- 第一次调用了类的静态成员方法(还没有生成实例对象)
- 还有其他可能……