Java对象初始化
自動(dòng)初始化(默認(rèn)值)
一個(gè)類的所有基本數(shù)據(jù)成員都會(huì)得到初始化,運(yùn)行下面的例子可以查看這些默認(rèn)值:
class Default{boolean t;char c;byte b;short s;int i;long l;float f;double d;public void show() {System.out.println("基本類型 初始化值\n"+"boolean<----->" + t +"\n" +"char<----->" + c +"\n" +"byte<----->" + b + "\n" +"short<----->" + s + "\n" +"int<----->" + i + "\n" +"long<----->" + l + "\n" +"float<----->" + f + "\n" +"double<----->" + d + "\n");} } public class InitValue {public static void main(String[] args) {Default d = new Default();d.show();} }【運(yùn)行結(jié)果】:
基本類型 初始化值 boolean<----->false char<-----> byte<----->0 short<----->0 int<----->0 long<----->0 float<----->0.0 double<----->0.0其中,char類型的默認(rèn)值為空(null)。
對于非基本數(shù)據(jù)類型而言,對象的句柄也會(huì)被初始化:
class Person {private String name;// setter } class Default {Person p;public void show() {System.out.println("Person<----->" + p);} } public class InitValue {public static void main(String[] args) {Default d = new Default();d.show();} }【運(yùn)行結(jié)果】:
Person<----->null可見,句柄初始化值為null。這就是說,如果沒有為p指定初始化值就調(diào)用類似于p.setName的方法,就會(huì)出現(xiàn)異常。
規(guī)定初始化
如果需要自己為變量賦一個(gè)初始值,可以在定義變量的同時(shí)賦值。
class Default{boolean t = true;char c = 'A';byte b = 47;short s = 0xff;int i = 24;long l = 999;float f = 1.2f;double d = 1.732;public void show() {System.out.println("boolean<----->" + t +"\n" +"char<----->" + c +"\n" +"byte<----->" + b + "\n" +"short<----->" + s + "\n" +"int<----->" + i + "\n" +"long<----->" + l + "\n" +"float<----->" + f + "\n" +"double<----->" + d + "\n");} } public class InitValue {public static void main(String[] args) {Default d = new Default();d.show();} }甚至可以通過一個(gè)方法來進(jìn)行初始化;
class Person {int i = set();//... }這些方法也可以使用自變量:
class Person {int i;int j = set(i);//... }構(gòu)建器初始化
構(gòu)建器進(jìn)行初始化的優(yōu)點(diǎn)是可以在運(yùn)行期決定初始化值。例如:
class Person {int age;Person() {age = 89;} }age首先會(huì)初始化為0,然后變成89。對于所有基本類型以及對象的句柄,這種情況都是成立的。
初始化順序
在一個(gè)類里,初始化的順序是由變量在類內(nèi)的定義順序決定的。即使變量定義大量遍布于方法定義的中間,那么變量仍然會(huì)在調(diào)用任何方法(包括構(gòu)造函數(shù))之前得到初始化。例如:
class Pet {Pet(int age) {System.out.println("Pet(" + age + ")");} }class Person {Pet t1 = new Pet(1);Person() {System.out.println("---Person()---");t3 = new Pet(33);}Pet t2 = new Pet(2);void show() {System.out.println("show----running");}Pet t3 = new Pet(3); }public class OrderOfInitialization {public static void main(String[] args) {Person p = new Person();p.show();} }【運(yùn)行結(jié)果】:
Pet(1) Pet(2) Pet(3) ---Person()--- Pet(33) show----running上例中,雖然t1、t2、t3的定義遍布于類中,但是初始化的先后順序是由t1、t2、t3的定義順序決定的(自己動(dòng)手調(diào)換t1、t2、t3看看結(jié)果),且初始化優(yōu)先于構(gòu)建器執(zhí)行,當(dāng)調(diào)用Person的構(gòu)建器時(shí),t3重新初始化。
靜態(tài)數(shù)據(jù)的初始化
如果數(shù)據(jù)是靜態(tài)的(static),同樣的過程也會(huì)執(zhí)行。若屬于基本類型,而且未對其進(jìn)行初始化,就會(huì)自動(dòng)獲得自己的標(biāo)準(zhǔn)基本類型初始值;若它是指向一個(gè)對象的句柄,除非創(chuàng)建一個(gè)對象同它連接起來,否則得到一個(gè)空值(null)。如果在定義時(shí)初始化,采取的方式與非靜態(tài)值是不同的,這是因?yàn)閟tatic只有一個(gè)存儲(chǔ)區(qū)域。例如:
class Bowl {Bowl(int marker) {System.out.println("Bowl(" + marker + ")");}void f(int marker) {System.out.println("f(" + marker + ")");} }class Table {static Bowl b1 = new Bowl(1);Table() {System.out.println("Table()");b2.f(1);}void f2(int marker) {System.out.println("f2(" + marker + ")");}static Bowl b2 = new Bowl(2); }class Cupboard {Bowl b3 = new Bowl(3);static Bowl b4 = new Bowl(4);Cupboard() {System.out.println("Cupboard()");b4.f(2);}void f3 (int marker) {System.out.println("f3(" + marker + ")");}static Bowl b5 = 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();t2.f2(1);t3.f3(1);}static Table t2 = new Table();static Cupboard t3 = new Cupboard(); }【運(yùn)行結(jié)果】:
Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1)靜態(tài)代碼塊
Java允許將其他static初始化工作劃分到類內(nèi)一個(gè)特殊的代碼塊中,這種代碼塊的形式為static關(guān)鍵字,后面跟著一個(gè)方法主體,稱為靜態(tài)代碼塊。靜態(tài)代碼塊只有在第一次生成那個(gè)類的對象或首次訪問屬于那個(gè)類的static成員時(shí)執(zhí)行。例如:
class Person {Person(int age) {System.out.println("Person(" + age + ")");}void f(int age) {System.out.println("f(" + age + ")");} }class Persons {static Person p1;static Person p2;static {p1 = new Person(1);p2 = new Person(2);}Persons() {System.out.println("Persons()");} }public class ExplicitStatic {public static void main(String[] args) {System.out.println("Inside main()");Persons.p1.f(18);//1 }static Persons x = new Persons();//2static Persons y = new Persons();//2 }在標(biāo)記為1的行內(nèi)訪問static對象p1的時(shí)候,或在行1被注釋而行2未被注釋是,用于Persons的static初始化模塊就會(huì)運(yùn)行。若1和2都被注釋掉,則用于Persons的靜態(tài)代碼塊不會(huì)執(zhí)行。
靜態(tài)屬性和靜態(tài)代碼塊執(zhí)行的先后順序
class Person {Person(int age) {System.out.println("Person("+age+")");} } class Persons {static Person p = new Person(2); // 1static {p = new Person(3);}static Person p = new Person(2); // 2 } public class CompStaticInit {public static void main(String[] args) {}static Persons x = new Persons(); }根據(jù)注釋1保留2,注釋2保留1的結(jié)果分析可知,靜態(tài)屬性和靜態(tài)代碼塊的執(zhí)行順序取決于編碼的順序。誰在前面就先執(zhí)行誰。
非靜態(tài)屬性的初始化
class Animal {Animal(int age) {System.out.println("Animal(" + age + ")");}void f(int age) {System.out.println("f(" + age + ")");} } public class NotStaticInit {Animal a1;Animal a2;{a1 = new Animal(1);a2 = new Animal(2);System.out.println("a1 & a2 initialized");}NotStaticInit() {System.out.println("NotStaticInit");}public static void main(String[] args) {System.out.println("Inside main()");NotStaticInit x = new NotStaticInit();} }類似于靜態(tài)代碼塊,匿名代碼塊與非靜態(tài)屬性的初始化順序取決于編碼順序。
繼承中的對象初始化過程
class Insect {int i = 1;int j;Insect() {prt("i = " + i + ", j = " + j);j = 2;}static int x1 = prt("static Insect.x1 initialized");static int prt(String s) {System.out.println(s);return 3;} }public class Beetle extends Insect {int k = prt("Beeklt.k initialized");Beetle() {prt("k = " + k);prt("j = " + j);}static int x2 = prt("static Bootle.x2 initialized");static int prt(String s) {System.out.println(s);return 4;}public static void main(String[] args) {prt("Beetle constructor");Beetle b = new Beetle();} }【運(yùn)行結(jié)果】:
static Insect.x1 initialized static Bootle.x2 initialized Beetle constructor i = 1, j = 0 Beeklt.k initialized k = 4 j = 2對Beetle運(yùn)行Java時(shí),發(fā)生的第一件事情是裝載程序到外面找到那個(gè)類。在裝載過程中,裝載程序發(fā)現(xiàn)一個(gè)基礎(chǔ)類,所以隨之將其載入。無論是否生成基礎(chǔ)類的對象,這一過程都將執(zhí)行。如果基礎(chǔ)類含有另一個(gè)基礎(chǔ)類,則另一個(gè)基礎(chǔ)類隨即也會(huì)載入,以此類推。接下來就在根基礎(chǔ)類中執(zhí)行static初始化,再在下一個(gè)衍生類中執(zhí)行,以此類推。這是因?yàn)檠苌惖某跏蓟赡芤蕾囉趯A(chǔ)類成員的初始化。
當(dāng)類都裝載完畢,就能創(chuàng)建對象。首先,這個(gè)對象中的所有基本數(shù)據(jù)類型都會(huì)設(shè)置成為他們的默認(rèn)值,對象句柄設(shè)為null。然后執(zhí)行基礎(chǔ)類的構(gòu)建器。這種情況是自動(dòng)完成的(衍生類的構(gòu)造函數(shù)中默認(rèn)調(diào)用了super(),也可以通過super指定基類的構(gòu)建器)。基礎(chǔ)類構(gòu)建器完成后,衍生類實(shí)例變量就會(huì)按本來的順序得到初始化,然后執(zhí)行構(gòu)建器的剩余的主體部分。
總結(jié)對象創(chuàng)建的過程:
- 靜態(tài)只在類加載的時(shí)候執(zhí)行且只執(zhí)行一次;
- 非靜態(tài)只有在實(shí)例化的時(shí)候執(zhí)行,每次創(chuàng)建對象都執(zhí)行;
- 靜態(tài)在非靜態(tài)之前執(zhí)行,基類靜態(tài)優(yōu)先于衍生類靜態(tài)執(zhí)行;
- 靜態(tài)屬性和靜態(tài)代碼塊的執(zhí)行屬性取決于它們在類中的位置,誰在前先執(zhí)行誰;
- 非靜態(tài)屬性和構(gòu)造塊的執(zhí)行順序取決于它們在類中的位置,誰在前執(zhí)行誰。
轉(zhuǎn)載于:https://www.cnblogs.com/xiaoxiaoyihan/p/4934839.html
總結(jié)
- 上一篇: Memcached 缓存个体,对象,泛型
- 下一篇: 关于思考写程序的意义