实践时最好的学习方法。
类加载(下面会用到)的定义:当JVM第一次使用一个类时候,需要通过classpath找到.class字节码文件,读入这个类中的信息(包名,类型,属性,方法,静态变量,静态方法),并且保存在虚拟机中,而且类加载只进行一次。
类加载的时机:
1,创建对象时;2,通过(类名.静态成员名)访问静态成员时;3,子类进行类加载时(包括前面1和2两种情况)
现在总结有父类时对象的创建过程总体:
第1步:被static修饰的成员方法、属性和代码块之后就变成了静态成员方法、静态属性和静态代码块,和static修饰符有关的都是和对象无关的,所以在创建对象的时候会先执行父类类加载执行静态代码块,然后才进行子类的类加载执行子类的静态代码块。
第2步:a 为父类属性赋默认值; b 父类(动态)代码块和成员属性的位置等同,没有先后只会按照从上到下的顺序执行 c 调用父类的构造方法
第3步:子类再执行重复父类abc操作
第一步:进行了类加载
类加载的定义:
day12;//对象创建过程
/*
结果我粘贴在最上面。
Super的静态代码块执行第1次
Sub的静态代码块执行第1次
为Super属性赋默认值
Super的动态代码块执行第1次
Super的无参构造函数
Sub的动态代码块执行第1次
为Sub类赋默认值
Sub的无参构造函数
为Super属性赋默认值
Super的动态代码块执行第2次
Super的无参构造函数
Sub的动态代码块执行第2次
为Sub类赋默认值
Sub的无参构造函数
Process finished with exit code 0
*/
public class Test00{
public static void main(String[] args){
Super s1 = new Sub();
Super s2 = new Sub();
}
}
class Super{
static int countSuper = 0;//动态代码块的 计数器
Super(){//无参构造
System.out.println("Super的无参构造函数");
}
int sup = Super.getNumber();//Super类赋默认值
//动态代码块
{
System.out.println("Super的动态代码块执行第"+(++countSuper)+"次");
}
static int countStaticSuper = 0;
static {
System.out.println("Super的静态代码块执行第"+(++countStaticSuper)+"次");
}
//为属性赋默认值做标记
public static int getNumber(){
System.out.println("为Super属性赋默认值");
return 0;
}
}
class Sub extends Super{
static int countSub = 0;//动态代码块的计数器
{
System.out.println("Sub的动态代码块执行第"+(++countSub)+"次");
}
int sub = Sub.getNumber();//Sub为属性赋默认值
static int countStaticSub = 0;//静态代码块计数器
static {
System.out.println("Sub的静态代码块执行第"+(++countStaticSub)+"次");
}
Sub(){
System.out.println("Sub的无参构造函数");
}
//由于静态方法没有多态,可以覆盖
public static int getNumber(){
System.out.println("为Sub类赋默认值");
return 0;
}
}