java初始化顺序

今天考试初始化顺序错了好几题,整理后做一个总结吧。
   内容主要有:静态属性变量,变量,静态代码块,构造代码块,构造函数,静态方法,普通方法,子类,父类
初始化顺序:
先声明,后赋值;
先属性,后方法;
先静态,后非静态;
先父类,后子类
——————————————第一个例子——————————————————
先举简单的例子来说:
public class Demo {


static{
System.out.print("静态块top——————\n");
}
public static int k=0;
public static Demo t1=new Demo("t1");
public static int i=print("i");
public static int n=99;

private int a=3;
public int ttt=pri("ttt");


{
System.out.println("构造块");
}

static{
System.out.println("静态块");
}
public Demo(String string) {
System.out.println(string);
}
public int pri(String str){
System.out.println(str);
return 888;
}
private static int print(String string) {
System.out.println(string);
return 1;
}
public static void main(String[] args) {


}
}
****************
先声明:
k=0;
t1=null;
i=0;
n=0;
a=error——先声明静态的,后非静态的,所以这个时候非静态的a还没有声明
这是第一轮声明,声明的时候静态属性都会有系统默认值,顺序是从上往下。
那么声明属性之后静态方法有没有声明?个人觉得应该是声明的(至于先声明静态属性还是静态方法或者
按顺序声明还没想到办法验证,但这并没关系)。因为第一个静态代码块调用下面的静态方法也是可以调用的。
所以下面的静态方法是声明了,但声明并不等于调用执行。
所以上面的代码可以理解成:
静态属性:
k=0;
t1=null;
t2=null;
i=0;
n=0;
静态方法:
第一个static{}
第二个static{}
static的println(string)
main(args)
变量:
a=error
ttt=error
实例方法:
构造块方法=error
构造函数=error
pri=error
说的简单点,第一轮声明静态属性和静态方法,顺序无所谓。
******************
后赋值(静态属性和方法 依照从上往下的顺序执行):
执行static代码块:
static{
System.out.print("静态块top——————\n");
}
k=0;
t1=new StaticTest("t1");
t1要实例化对象,这个怎么执行呢?
初始化的时候依据现在的执行状态生成一个对象,生产对象的之前需要把没有完成的继续完成。
现在的状态是:
输出过一句:静态块top——————
k=0;
t1在初始化
t2=null;
i=0;
n=0;
a=error
ttt=error
构造块方法=error
pri=error
需要完成:
a=0;
ttt=pri("ttt");——调用方法输出"ttt"  方法不用看了,因为只有调用才会执行
初始化之前调用(优先级和变量一样,如果下面还有变量,则会继续赋值变量):
{
System.out.println("构造块");——输出"构造块"
   }
初始化:
public Demo(String string) {
System.out.println(string);——输出"t1"
}
i=print("i");
        调用print方法:
System.out.println(string);——输出"i"
i=1;
n=99;
static{
System.out.println("静态块");——输出"静态块"
}
进入static的main方法
public static void main(String[] args) {
这个时候变量比如a还没有声明,所以如果想要打印a是会报错的。
为什么说还没有声明?因为Debug的时候,a=error,如果申明了,则会有默认的初始值
}
***************************
这个例子就讲完了。
输出结果:


静态块top——————
ttt
构造块
t1
i
静态块
**
初始化的过程是:
先声明静态属性和方法,静态属性赋值默认值,方法声明但不调用执行
后赋值静态属性和方法,按 顺序 执行,main方法也只是一个静态方法,如果下面还有静态代码块,则执行完main方法后最后还会调用下面的静态代码块。
需要注意和理解的点:
1  静态属性和非静态属性生成一个实例变量(new)的时候,执行未赋值的变量然后初始化,不管静态属性中是否还有未赋值元素
2  静态代码块,静态属性,静态方法优先级一样,按照顺序执行
3  变量和实例方法一起声明,声明后实例方法就可以调用,所以变量赋值的时候可以调用实例方法。
4  优先级:静态属性=静态代码块>mian方法(上面没有体现,可以自己测试)
静态代码块放在静态属性前后,按顺序执行
静态属性 和 main方法比较:先属性,后方法
静态代码块放在main方法前后,都会在main之前执行
优先级:全局变量属性=全局构造代码块>构造方法
构造代码块无论放在构造方法前后,都先执行构造代码块
全局变量属性放在构造代码块前后,按顺序执行
全局变量属性和构造方法:先属性,后方法



所以,如果理解了这个例子,就能明白两个问题:
1  为什么静态方法只能调用静态属性和静态方法?——静态属性和静态方法调用执行的时候,非静态属性和方法都没有声明怎么调用呢?
2  为什么变量和方法依赖于对象——因为实例化对象的时候才执行
——————————————第二个例子——————————————————
这个例子是对上面内容举例和补充,如果能正确写出答案,差不多理解了初始化顺序
public class StaticTest {


static{
print("+++++++++++++");
}
public  static int k=0;
public static StaticTest t1=new StaticTest("t1");
public static StaticTest t2=new StaticTest("t2");
public static int i=print("i");
public static int n=99;

private int a=0;
public int ttt=pri("ttt");


{
print("构造块");
}

static{
print("静态块");
}
public int j=print("j");
public StaticTest(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++i;
++n;
}
private int pri(String str) {
System.out.println(str);
return 0;
}
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}

public static void main(String[] args) {
StaticTest tt=new StaticTest("init");

}
}
*********************
声明:
静态属性:
k=0;
t1=null;
t2=null;
i=0;
n=99;
静态方法:
static{}
print(){}
main(){}
*************
赋值:
static{
print("+++++++++++++");
}
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
执行前:k=0,i=0,n=0;
执行:
输出:1:+++++++++++++    i=0  n=0
k=1;
n=1;
i=1;
k=0;——k又变成0了
t1=new StaticTest("t1");
现在的状态:k=0;i=1,n=1;
执行:
先变量:
a=0;
ttt=pri("ttt");
private int pri(String str) {
System.out.println(str);
return 0;
}
输出:"ttt"
ttt=0;
{
print("构造块");
}
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
输出:1:构造块    i=1  n=1
k=1,i=2,n=2;
j=print("j");
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
输出:2:j    i=2  n=2
k=2,i=3,n=3;
初始化:
public StaticTest(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++i;
++n;
}
输出:3:t1    i=3  n=3
k=3,i=4,n=4;
t2=new StaticTest("t2");
现在的状态:k=3,i=4,n=4;
执行:
先变量:
a=0;
ttt=pri("ttt");
private int pri(String str) {
System.out.println(str);
return 0;
}
输出:"ttt"
ttt=0;
{
print("构造块");
}
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
4:构造块    i=4  n=4
k=4,i=5,n=5;
j=print("j");
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
5:j    i=5  n=5
k=5,i=6,n=6;
初始化:
public StaticTest(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++i;
++n;
}
6:t2    i=6  n=6
k=6,i=7,n=7;
i=print("i");
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
输出:7:i    i=7  n=7
k=7,n=8,i=8;
i=8;
n=99;
static{
print("静态块");
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
8:静态块    i=8  n=99
k=8,i=9,n=100;
}


public static void main(String[] args) {
StaticTest tt=new StaticTest("init");
现在的状态:k=8,i=9,n=100;
执行:
先变量:
a=0;
ttt=pri("ttt");
private int pri(String str) {
System.out.println(str);
return 0;
}
输出:"ttt"
ttt=0;
{
print("构造块");
}
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
9:构造块    i=9  n=100
k=9,i=10,n=101;
j=print("j");
private static int print(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++n;
return ++i;
}
10:j    i=10  n=101
k=10,i=11,n=102;
初始化:
public StaticTest(String str) {
System.out.println((++k)+":"+str+"    i="+i+"  n="+n);
++i;
++n;
}
11:init    i=11  n=102
k=11,i=12,n=103;
}
结果:


1:+++++++++++++    i=0  n=0
ttt
1:构造块    i=1  n=1
2:j    i=2  n=2
3:t1    i=3  n=3
ttt
4:构造块    i=4  n=4
5:j    i=5  n=5
6:t2    i=6  n=6
7:i    i=7  n=7
8:静态块    i=8  n=99
ttt
9:构造块    i=9  n=100
10:j    i=10  n=101
11:init    i=11  n=102
*****


——————————————第三个例子——————————————————
class Parent {
public static String p_StaticField = "父类--静态变量";
public String p_Field = "父类--变量"; 
static {    
System.out.println(p_StaticField);    
        System.out.println("父类--静态初始化块"); 
    }  

{    
System.out.println(p_Field);    
        System.out.println("父类--初始化块");    
    }


public Parent() {    
System.out.println("父类--构造器");    
    }    
}    


public class SubClass extends Parent {        
    public static String s_StaticField = "子类--静态变量";      
    public String s_Field = "子类--变量";    
    static {    
        System.out.println(s_StaticField);    
        System.out.println("子类--静态初始化块");    
    }     
  
    {    
        System.out.println(s_Field);    
        System.out.println("子类--初始化块");    
    }    


    public SubClass() {    
        System.out.println("子类--构造器");    
    }    


    public static void main(String[] args) {    
        new SubClass();    


    } 
}


结果:


"父类--静态变量"
"父类--静态初始化块"
"子类--静态变量"
"子类--静态初始化块"
"父类--变量"
"父类--初始化块"
"父类--构造器"
"子类--变量"
"子类--初始化块"
"子类--构造器"
*********
继承的时候,先父类,后子类
加载子类之前需要先加载父类,问题是调用子类的构造函数之前,是先调用子类的构造块 还是先调用父类的构造块和构造函数?事实是系统调用是先调用父类的构造块,父类的全部调用好了,再处理子类
——————————————第四个例子——————————————————
 


public class TestOrder {
public static TestA a = new TestA(); 
static {    
        System.out.println("静态初始化块");    
}  
public static TestB b = new TestB();
public static void main(String[] args) {  
new TestOrder();
}
}


class TestA {
public TestA() {
System.out.println("Test--A");
}
}


class TestB {
public TestB() {
System.out.println("Test--B");
}
}
结果:


"Test--A"
"静态初始化块"

"Test--B"


——————————————第五个例子——————————————————

class HelloA {

    public HelloA() {
        System.out.println("HelloA");
    }
    
    { System.out.println("I'm A class"); }
    
    static { System.out.println("static A"); }

}

public class HelloB extends HelloA {
    public HelloB() {
        System.out.println("HelloB");
    }
    
    { System.out.println("I'm B class"); }
    
    static { System.out.println("static B"); }
    
    public static void main(String[] args) { 
     new HelloB(); 
   }

}
结果:

static A
static B
I'm A class
HelloA
I'm B class
HelloB

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值