在Java中,static修饰符一直都是很重要的知识点,特别是当它修饰为一个静态代码块的时候,还有它被用来修饰变量的时候,当发生继承关系或者是内部类关系的时候,我们这里分几种情况进行讨论
当发生继承关系的时候
如:
1 | public class SuperClass { |
1 | public final class SonClass extends SuperClass { |
在这里定义了一个静态函数,而静态函数是属于类的,而并不属于示例,我们可以通过一下两个方式验证
- 当使用静态函数的时候
1 | public static void main(String[] args) { |
结果为
- 当new对象的时候
1 | public static void main(String[] args) { |
结果为
- 两种情况全部存在的时候
1 | public static void main(String[] args) { |
结果为
结论
当使用静态函数的时候,先初始化父类的静态变量,然后执行父类的静态代码块,然后再是子类的静态变量,静态代码块。当我们构造出一个对象的时候,也是先进行类的初始化,同上,在初始化完静态变量后,先是执行父类的非静态变量,然后是非静态代码块,最后才是父类的构造函数,然后是子类的这个过程,具体如下:
- 父类的静态变量及静态代码块
- 子类的静态变量及静态代码块
- 父类的非静态变量、非静态代码块、构造函数
- 子类的非静态变量、非静态代码块、构造函数
这里我们还可以得出的结论有
类的初始化只有一次,若实例化对象的时候,类已经进行了初始化,则不需要再重复进行
还有静态常量等在程序初始化的时候就已经初始化了,这是必须知道的。
静态内部类与非静态内部类
静态内部类如下:
1 | public static final class SonInner { |
这个类是在SonClass中的,我们可以实验一下
1 | public static void main(String[] args) { |
结果为:
结论
静态内部类的初始化不依赖外围类的初始化。
若是非静态内部类,则会发现在内部类中不能使用静态代码块与静态函数,只能先创建外围类再创建内部类
这时的初始化过程如下:
- 先按照父类子类的顺序初始化外围类
- 初始化内部类的非静态变量、非静态代码块
最后还需要注意的是,我们在静态函数中只需要定义函数是static的,不需要再加final关键字修饰