转载声明:文章来源https://blog.csdn.net/yangyan19870319/article/details/6202403
相信好多人对java初始化问题一直存有疑惑,下面是我看到的比较详细的java初始化问题讲解
一 java初始化基础知识
1、 一个类的所有基本类型数据成员都会保证获得一个初始值。
非基本类型,会初始化为null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Initialization { int a; char b; short s; float f; long lo; double dou; byte e; boolean flag; Object obj; public static void main(String [] args){ Initialization init = new Initialization(); init.print(); } public void print(){ System.out.println( "int a=" +a+ "/nchar b=" +b+ " /n" + " short s=" +s+ "/n float f=" +f+ "/n long lo=" +lo+ "/n double dou=" +dou+ "/n byte e=" +e+ "/n boolean flag=" +flag+ "/n Object obj=" +obj); } |
出来结果为
1 2 3 4 5 6 7 8 9 | int a=0 char b= short s=0 float f=0.0 long lo=0 double dou=0.0 byte e=0 boolean flag= false Object obj= null |
可见,java会为类的基本类型的变量提供一个初始值,各类型初始值不同,非基本类型初始为null。注意,这里的变量必须是类变量,注意,只会为类变量提供初始化,而局部变量不会。如果局部变量没有初始化,会收到一个出错信息
2、可以通过构造方法或其他方法进行初始化,但是不会妨碍java默认的初始化
看下面的例子
1 2 3 4 5 6 7 8 9 10 11 12 | int i; Object obj; public Initialization(){ System.out.println( "before i=" +i+ " obj=" +obj); i = 1; obj = new Object(); System.out.println( "after i=" +i+ " obj=" +obj); } public static void main(String [] args){ Initialization init = new Initialization(); } |
输出结果为
1 2 | before i=0 obj= null after i=1 obj=java.lang.Object@de6ced |
由此可见,不论是基本类型,还是其他的类。java默认的初始化是最先发生的,位于一切方法之前。
3、static 数据的初始化
static 数据会发生上述同样的事情(基本类型,获得对应基本类型的初始化值;非基本类型,初始化为null)
但是,由于static值只有一个存储区域,所以static值只会被初始化一次,看下面的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static void main(String [] args){ Cupboard cup = new Cupboard(); cup = new Cupboard(); } public class Cupboard { static Bowl bowl = new Bowl(); public Cupboard(){ System.out.println( "initialization Cupboard" ); } } public class Bowl { public Bowl(){ System.out.println( "init ing Bowl~" ); } } |
输出结果如下
1 2 3 | init ing Bowl~ initialization Cupboard initialization Cupboard |
所以说,static数据只会在第一次进行初始化,之后就不会了。
4、初始化顺序
在一个类中,无论变量的定义是在方法之前还是方法之后,都会在方法之前进行初始化的; 另外,static数据初始化位于非static数据初始化之前
来看下边的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public static void main(String [] args){ Cupboard cup = new Cupboard(); } public class Cupboard { Pan pan = new Pan(); public Cupboard(){ System.out.println( "initialization Cupboard" ); } static Bowl bowl = new Bowl(); } public class Bowl { public Bowl(){ System.out.println( "init ing Bowl~" ); } } public class Pan { public Pan(){ System.out.println( "initialization Pan" ); } } |
结果如下
1 2 3 | init ing Bowl~ initialization Pan initialization Cupboard |
5、静态块
静态块里的变量初始化顺序位于普通变量之前,和static变量相比,则是完全由定义的顺序来决定了。另外,静态块里的变量也是只初始化一次,这点和static变量一致。示例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class Other { static{ Bowl bowl2 = new Bowl(2); } static Bowl bowl = new Bowl(1); private Bowl bowl3 = new Bowl(3); public static void main(String [] args){ Other other = new Other(); other = new Other(); } } public class Bowl { public Bowl(){ System.out.println( "init ing Bowl~" ); } public Bowl(int i){ System.out.println( "init ing Bowl" +i); } } |
输出结果为
1 2 3 4 | init ing Bowl2 init ing Bowl1 init ing Bowl3 init ing Bowl3 |
如果调换static变量和静态块的位置,输出结果如下
1 2 3 4 | init ing Bowl1 init ing Bowl2 init ing Bowl3 init ing Bowl3 |
6、涉及到继承时 初始化顺序
初始化时,如果有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中,它们二者之间的顺序,可参见第5点; static变量初始完了后,先初始化父类,然后是子类。
示例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Base { Bowl bowl = new Bowl(1); public Base(){ System.out.println( "initialization Class Base" ); } static Bowl bowl5 = new Bowl(5); static{ Bowl bowl6 = new Bowl(6); } } public class Sub extends Base { Bowl bow2 = new Bowl(2); public Sub(){ System.out.println( "initialize Sub" ); } static Bowl bowl3 = new Bowl(3); static{ Bowl bowl4 = new Bowl(4); } } public class Test { public static void main(String []args){ Sub sub = new Sub(); } } |
输出结果如下
1 2 3 4 5 6 7 8 | init ing Bowl5 init ing Bowl6 init ing Bowl3 init ing Bowl4 init ing Bowl1 initialization Class Base init ing Bowl2 initialize Sub |
二 问题举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package test; class Singleton { private static Singleton obj = new Singleton(); public static int counter1; public static int counter2 = 0; private Singleton() { counter1++; counter2++; } public static Singleton getInstance() { return obj; } } public class MyMain { public static void main(String[] args) { Singleton obj = Singleton.getInstance(); System.out.println( "obj.counter1==" +obj.counter1); System.out.println( "obj.counter2==" +obj.counter2); } } |
这段程序代码输出,实际运行结果:
obj.counter1==1
obj.counter2==0
相信大家跟我一样会对这个结果存有疑问,这段代码中尤其注意:private static Singleton obj = new Singleton(); 在类Singleton中的位置,改变位置会有不同结果。关于这段代码运行结果的解释:
当程序执行private static Singleton obj = new Singleton(); 句的时候就去调用了Singleton构造器,此时counter1、counter2都是1,但是接着执行向下执行:public static int counter1;时将1赋给counter1,执行public static int counter2 = 0;时重新给counter2赋值为0
三 典型初始化例子
Java初始话很好的一个例子, 摘自Think in Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | package cn.edu.xupt.test; //: initialization/StaticInitialization.java //Specifying initial values in a class definition. //无论创建多少对象, 静态数据都只占用一份存储区域 //初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化), 而后是"非静态"对象 //载入.class文件(这将创建Class对象),有关静态初始化的所有动作执行. //静态初始化只在Class对象首次加载的时候进行一次 class Bowl { Bowl(int marker) { System.out.println( "Bowl(" + marker + ")" ); } void f1(int marker) { System.out.println( "f1(" + marker + ")" ); } } class Table { static Bowl bowl1 = new Bowl(1); Table() { System.out.println( "Table()" ); bowl2.f1(1); } void f2(int marker) { System.out.println( "f2(" + marker + ")" ); } static Bowl bowl2 = new Bowl(2); } class Cupboard { Bowl bowl3 = new Bowl(3); static Bowl bowl4 = new Bowl(4); Cupboard() { System.out.println( "Cupboard()" ); bowl4.f1(2); } void f3(int marker) { System.out.println( "f3(" + marker + ")" ); } static Bowl bowl5 = new Bowl(5); } public class StaticInitialization { public static void main(String[] args) { System.out.println( "Creating new Cupboard() in main" ); new Cupboard(); System.out.println( "Creating new Cupboard() in main" ); new Cupboard(); table.f2(1); cupboard.f3(1); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); } /* * Output: * Bowl(1) Bowl(2) Table() f1(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) f2(1) f3(1) */ // :~ |
帖子还没人回复快来抢沙发