在了解java类加载机制的时候,我们有时候会遇到一些谁先谁后的问题,我们当然不能一眼看出来,我们需要实践代码来总结结论
下面是我封装好两个类
public class People {
private String name;
private int age;
private static String a = father();
public static String father()
{
System.out.println("父类静态变量");
return "父类静态变量";
}
static {
System.out.println("父类静态块");
}
{
System.out.println("父类非静态块");
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
public People(){
System.out.println("父类构造方法");
}
public void speak(){
System.out.println("我是人");
}
}
public class Student extends People {
private String stuNo;
static {
System.out.println("子类静态块");
}
private static String b = child();
public static String child()
{
System.out.println("子类静态变量");
return "子类静态变量";
}
public Student(String name, int age, String stuNo) {
super(name, age);
this.stuNo = stuNo;
}
public Student(String stuNo) {
this.stuNo = stuNo;
}
public Student(){
System.out.println("子类构造方法");
}
{
System.out.println("子类非静态块");
}
@Override
public void speak(){
System.out.println("我是学生");
}
}
我们新建了两个学生对象,并且执行了代码的结果如图所示:
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("================================");
Student s2 = new Student();
}
我们有了代码运行的基础可以总结出来以下几点:
1.所有的静态变量,无论是父类还是子类只会被加载一次。
其中 静态代码块,在类被加载的时候运行,因此只加载一次,且优先于其他变量,常用于运行一些项目启动时需要运行的代码,比如加载项目需要的系统资源等等。静态变量 所有该类的对象共同具有的属性。
2.静态变量的加载顺序与代码的书写顺序有关
我们可以发现父类与子类的静态块与静态变量加载的顺序不一样,因为我们的书写顺序不同。
3.代码块顺序优先于构造方法
构造代码块(代码块),在创建对象的时候执行,且先于构造函数执行。目的也是用于初始化对象,关于和构造函数的不同,我的理解是,如果有多个不同参数的构造函数,就可以提取他们共同的初始化语句到构造代码块,减少重复。
4.如果一个类具有父类,在类加载的时候都是先加载父类的方法(相当于构造了一个父类对象)
- 子类继承父类后,获取到父类的属性和方法,这些属性和方法在使用前必须先初始化,所以须先调用父类的构造器进行初始化。
- 在子类构造器的第一行会隐式的调用 super();,即调用父类的构造器
如果父类中没有定义空参的构造器,则必须在子类的构造器的第一行显示的调用super(参数); ,以调用父类中构造器
如果子类中构造器的第一行写了this();,则就隐式的super();会消失,因为super()和this()都只能在构造器的第一行定义
下面我们更改测试代码:
People p1 =new People();
System.out.println("================================");
Student s1 = new Student();
System.out.println("================================");
Student s2 = new Student();
!!再一次向我们证明
不管是父类还是子类加载(静态变量和静态语句块)都只能加载一次。
不管是父类还是子类加载(非静态变量和非静态语句块和构造函数)都可重复加载