先类初始化
单个类 按照正常类的加载顺序加载,就是将类通过类加载器加载到内存 有继承 先加载父类再加载子类,就是先将父类通过类加载器加载到内存,然后就是子类
再成员属性
单个类 类初始化后,加载有静态的到方法区,然后没有静态的属性到栈空间 有继承 类初始化后,加载有父类静态的到方法区,然后子类静态的到方法区,再加载父类的没有静态的属性到栈空间,最后加载子类的没有静态的属性到栈空间
最后实例化初始化
首先实例化初始化必须要知道的知识
实列化之前会默认调用父类的无参构造,也就是要创建父类的对象将没有静态的属性(成员变量)从栈空间到堆空间重新初始化。(这里解释一下看不懂可以不看这个解析:栈空间保留的是变量名,对空间保留的是对应的地址值【值】)然后执行普通代码块,也就是普通代码块实例化对象时才会执行,其他时候都不会执行最后再调用构造方法,有参就调用有参的,反之亦然。
这里的第2步和第3步,不分先后顺序,也就是,谁写在前面就先执行谁
类和静态属性,静态代码块,只用再内存中加载一次就行,对于不是静态的成员(这个也叫非静态实例变量)变量和普通代码块的实列化几次就初始化几次
单个类
为了方便记忆,我从类的初始化开始写 类----》静态属性----》静态代码块------》非静态属性(或者普通代码块)-----》构造方法
有继承
为了方便记忆,我从类的初始化开始写 类----》父类静态属性----》父类静态代码块------》子类静态属性----》子类静态代码块------》父类非静态属性(或者普通代码块)-----》父类构造方法------》子类非静态属性(或者普通代码块)-----》子类构造方法
实列化一次就进行一次上面的步骤(记住类和静态的只在内存中加载一次)
对于一般的初始化运用上面的肯定没问题
对于初始化成员变量时,还直接赋值的,需要对继承和静态,this,super有一定的了解 来道简单的题练下手
public class Test08 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
class Fu{
private static int i = getNum("(1)i");
private int j = getNum("(2)j");
static{
print("(3)父类静态代码块");
}
{
print("(4)父类非静态代码块,又称为构造代码块");
}
Fu(){
print("(5)父类构造器");
}
public static void print(String str){
System.out.println(str + "->" + i);
}
public static int getNum(String str){
print(str);
return ++i;
}
}
class Zi extends Fu{
private static int k = getNum("(6)k");
private int h = getNum("(7)h");
static{
print("(8)子类静态代码块");
}
{
print("(9)子类非静态代码块,又称为构造代码块");
}
Zi(){
print("(10)子类构造器");
}
public static void print(String str){
System.out.println(str + "---->" + k);
}
public static int getNum(String str){
print(str);
return ++k;
}
}
(1)i->0
(3)父类静态代码块->1
(6)k----->0
(8)子类静态代码块----->1
(2)j->1
(4)父类非静态代码块,又称为构造代码块->2
(5)父类构造器->2
(7)h----->1
(9)子类非静态代码块,又称为构造代码块----->2
(10)子类构造器----->2
来最后一道会了就可以出师的题 (谁会写这种要人命的初始化, )
/*
* 对于T来说,就完成类初始化
*
* 创建对象,调用类的实例初始化()或(String str)
*
* (1)静态变量的显式赋值
* k = 0;
t1 = new T("t1");
(String str)
①j = print("j");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 1:j i=0 n=0
++n; n=1 k=1
return ++i; i=1
}
② {
print("构造块");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 2:构造块 i=1 n=1
++n; n=2 k=2
return ++i; i=2
}
}
③public T(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 3:t1 i=2 n=2
++n; n=3 k=3
++i; i=3
}
* t2 = new T("t2");
(String str)
①j = print("j");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 4:j i=3 n=3
++n; n=4 k=4
return ++i; i=4
}
② {
print("构造块");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 5:构造块 i=4 n=4
++n; n=5 k=5
return ++i; i=5
}
}
③public T(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 6:t2 i=5 n=5
++n; n=6 k=6
++i; i=6
}
i = print("i");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 7:i i=6 n=6
++n; n=7 k=7
return ++i; i=7
}
n = 99;
* (2)静态代码块
* static{
print("静态块");
print方法代码如下:
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 8:静态块 i=7 n=99
++n; n=100 k=8
return ++i; i=8
}
}
*/
public class T {
public static int k = 0;
public static T t1 = new T("t1");
public static T t2 = new T("t2");
public static int i = print("i");
public static int n = 99;
public int j = print("j");
{
print("构造块");
}
static{
print("静态块");
}
public T(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
++i;
}
public static int print(String str){
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public static void main(String[] args) {
}
}
来看看大佬怎么解的 https://www.cnblogs.com/cup-zh/p/9914622.html
对了对于有继承的来说,假如父类调用的方法,子类重写了的话,就直接调子类的这个方法,但是父类调用的这个方法是静态的,那就直接调用父类这个静态的方法