這是網(wǎng)易2015校招Java面試題,直接上題目。
題目package com.mousycoder.staticTest; 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(); } } class HelloA { public HelloA() { System.out.println("HelloA"); } { System.out.println("I’m A class"); } static { System.out.println("static A"); } }答案
static A static B I’m A class HelloA I’m B class HelloB()考察點
static 相關(guān)知識
非靜態(tài)代碼塊相關(guān)知識
類加載順序
解析存在父子關(guān)系,又有靜態(tài)代碼塊,先執(zhí)行父類靜態(tài)代碼塊,再執(zhí)行子類靜態(tài)代碼塊,故打印static A static B
存在父子關(guān)系,又有非靜態(tài)代碼塊,先執(zhí)行父類非靜態(tài)代碼塊,父類構(gòu)造器,再執(zhí)行子類非靜態(tài)代碼塊,子類構(gòu)造器故打印I"m A class HelloA I"m B class HelloB
結(jié)論靜態(tài)代碼塊=>非靜態(tài)代碼塊=>構(gòu)造方法
父子關(guān)系:父類靜態(tài)代碼塊=>子類靜態(tài)代碼塊=>父類非靜態(tài)代碼塊=>父類構(gòu)造函數(shù)=>子類非靜態(tài)代碼塊=>子類構(gòu)造函數(shù)
擴展知識 非靜態(tài)代碼塊{ System.out.println("I"m B class"); }
這個叫做非靜態(tài)代碼塊,也叫普通代碼塊,在每個類創(chuàng)建前(構(gòu)造函數(shù)之前)調(diào)用 ,不創(chuàng)建對象的時候,不被調(diào)用,代碼塊中定義的變量都是局部變量,如果有父子關(guān)系的話,先執(zhí)行父類的,再執(zhí)行子類的。非靜態(tài)代碼塊屬于對象,靜態(tài)代碼塊屬于類。
package com.mousycoder.staticTest; public class Child extends Father{ static { System.out.println("child-->static"); } private int n = 20; { System.out.println("Child Non-Static"); n = 30; } public int x = 200; public Child() { this("The other constructor"); System.out.println("child constructor body: " + n); } public Child(String s) { System.out.println(s); } public void age() { System.out.println("age=" + n); } public void printX() { System.out.println("x=" + x); } public static void main(String[] args) { new Child().printX(); } } class Father { static { //System.out.println("n+"+n); //當(dāng)n定義在下面時,會提示Cannot reference a field before it is defined, //所以必須把n定義移到上面才可以輸出 System.out.println("super-->static"); } public static int n = 10; public int x = 100; public Father() { System.out.println("super"s x=" + x); age(); } { System.out.println("Father Non-Static"); } public void age(){ System.out.println("nothing"); } }
結(jié)果:
super-->static child-->static Father Non-Static super"s x=100 age=0 Child Non-Static The other constructor child constructor body: 30 x=200
解析:
先執(zhí)行靜態(tài)代碼塊,有父子關(guān)系,先執(zhí)行父類靜態(tài)代碼塊,打印super-->static
執(zhí)行子類靜態(tài)代碼塊,打印child-->static
實例化子類的時候,先實例化父類,在調(diào)用父類構(gòu)造方法之前,先調(diào)用父類非靜態(tài)代碼塊,打印Father Non-Static
實例化父類,調(diào)用父類構(gòu)造方法,執(zhí)行第一句 System.out.println("super"s x=" + x); 在調(diào)用構(gòu)造方法之前,成員變量x 已經(jīng)被賦值為100,打印super"s x=100
執(zhí)行age()方法,因為main方法中真正實例化的是子類,子類又重寫了父類的age方法,所以執(zhí)行子類的age方法,此時子類還沒初始化,默認(rèn)n=0 ,打印age=0
實例化子類,調(diào)用子類構(gòu)方法之前,調(diào)用子類非靜態(tài)代碼塊,打印Child Non-Static
調(diào)用子類構(gòu)造方法,執(zhí)行this("The other constructor"),調(diào)用子類的Child(String s),打印The other constructor
執(zhí)行System.out.println("child constructor body: " + n); 初始化之前 成員變量初始值為20,執(zhí)行完非靜態(tài)代碼塊后 n被修改成30 ,所以這里n =30 打印child constructor body: 30
執(zhí)行printX()方法,打印x = 200
注意點:
子類重寫父類的方法
雖然非靜態(tài)代碼塊里是局部變量,但是可以改變類的成員變量的值
靜態(tài)代碼塊static { System.out.println("static B"); }
屬于靜態(tài)代碼塊,使用場景:1.想用一個存儲區(qū)域來保存一個特定的數(shù)據(jù),不想創(chuàng)建對象 2.創(chuàng)建一個特殊的方法,與這個類的對象沒有關(guān)聯(lián),即使沒創(chuàng)建對象,也可以調(diào)用
靜態(tài)變量靜態(tài)變量也叫做static變量,靜態(tài)變量和非靜態(tài)變量的區(qū)別在于靜態(tài)變量被所有的對象所共享,在內(nèi)存中只有一個副本,它當(dāng)且僅當(dāng)類初次加載時會被初始化,而非靜態(tài)變量是對象所擁有的,在創(chuàng)建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響 好處:1.可以用類名直接訪問(方便),也可以用對象訪問(不推薦) 2.只分配一次內(nèi)存,節(jié)省空間
靜態(tài)方法靜態(tài)方法就是不會被this和super的方法。特點:1.在static方法內(nèi)部不能調(diào)用所屬類的實例變量和實例方法(非靜態(tài)方法),但是可以在沒有創(chuàng)建任何對象的前提下,僅僅通過類本身(類名)來調(diào)用static方法 2.main方法就是static 方法,因為執(zhí)行main方法的時候,沒有創(chuàng)建任何對象,只能通過類名去訪問 3.沒有顯示聲明,類的構(gòu)造器也是靜態(tài)方法,參考:實例構(gòu)造器是不是靜態(tài)方法?
常見的錯誤Cannot make a static reference to the non-static field 就是靜態(tài)方法中引用了非靜態(tài)的的變量,靜態(tài)變量是不依賴對象而存在的,非靜態(tài)變量是依賴對象而存在的
示例:非靜態(tài)方法可以訪問靜態(tài)變量、方法,靜態(tài)方法是不可以訪問非靜態(tài)變量,方法
package com.mousycoder.staticTest; public class Test { private static String str1 = "111"; private String str2 = "ffffd"; public Test() { } public void print1() { System.out.println(str1); System.out.println(str2); print1(); } public static void print2(){ System.out.println(str1); System.out.println(str2); //報錯 Cannot make a static reference to the non-static field print1(); //報錯 } }靜態(tài)代碼塊
由static 關(guān)鍵字修飾的代碼塊叫做靜態(tài)代碼塊,特點:用于提高程序性能,類在初始化的時候,JVM會按照他們在類中出現(xiàn)的順序加載static 代碼塊,并且只會執(zhí)行一遍
示例:只生成一個String s 對象和一個String m 對象
package com.mousycoder.staticTest; import java.util.Date; public class HelloStatic { public static String s ; public static String m ; static { s = new String("hell"); m = new String("0"); } String hello() { String s = "hell"; String m = "o"; return s + m; } public static void main(String[] args) { Date start = new Date(); for (int i = 0; i < 1000000000 ; i++) { HelloStatic h = new HelloStatic(); h.hello(); } Date end = new Date(); System.out.println(end.getTime() - start.getTime()); } }
耗時:12ms
示例: 生成N個String s和String m對象
package com.mousycoder.staticTest; import java.util.Date; public class Hello { String hello() { String s = new String("hell"); String m = new String("o"); return s + m; } public static void main(String[] args) { Date start = new Date(); for (int i = 0; i < 1000000000; i++) { Hello h = new Hello(); h.hello(); } Date end = new Date(); System.out.println(end.getTime() - start.getTime()); } }
所用時間 9645ms
公共的變量應(yīng)該放到static里初始化,有利于提高效率
靜態(tài)變量訪問權(quán)static 變量是被所有對象共享的,只要該對象有權(quán)限,就可以訪問該變量
package com.mousycoder.staticTest; public class Main { static int value = 33; public static void main(String[] args) throws Exception{ new Main().printValue(); } private void printValue(){ int value = 3; System.out.println(this.value); } }
該輸出為:33 ,new Main()創(chuàng)建了一個對象,通過this.value是訪問的該對象的value 而int value = 3 是局部變量,并不是和該對象相關(guān)聯(lián)的,因為static變量是共享的,所以該對象可以訪問到value 值為 33 ,把this 去掉 則結(jié)果為 3
靜態(tài)變量相關(guān)面試題package com.mousycoder.staticTest; public class Test { Person person = new Person("Test"); static{ System.out.println("test static"); } public Test() { System.out.println("test constructor"); } public static void main(String[] args) { new MyClass(); } } class Person{ static{ System.out.println("person static"); } public Person(String str) { System.out.println("person "+str); } } class MyClass extends Test { Person person = new Person("MyClass"); static{ System.out.println("myclass static"); } public MyClass() { System.out.println("myclass constructor"); } }
順序是:
test static myclass static person static person Test test constructor person MyClass myclass constructor
執(zhí)行順序
test static =>new MyClass() => myclass static => new MyClass() => person static => Person person = new Person("Test") => person Test => Person person = new Person("Test") => test constructro => Person person = new Person("Myclass") => person MyClass => Person person = new Person("MyClass") => myclass contructor
說明:
執(zhí)行main方法,實例化MyClass
發(fā)現(xiàn)MyClass 有父類Test,首先實例化Test
加載Test類,這個時候會執(zhí)行static方法,打印 test static ,
然后要實例化MyClass 類,加載MyClass類,執(zhí)行static方法,打印myclass static
在所有類按照順序都加載完畢后,開始一個一個實例化類,先實例化父對象 Test類
在實例化之前,要先初始化成員變量,這個時候會執(zhí)行Person p = new Person("Test"),這個時候發(fā)現(xiàn)Person類還沒有被加載過,因此先加載Person類
執(zhí)行Person類的static方法,打印person static 接著實例化Person p = new Person("Test") 調(diào)用Person的構(gòu)造方法,打印person Test
然后開始調(diào)用Test的構(gòu)造方法,打印test constructor,Test類初始化完畢
開始實例化Myclass類,首先還是初始化MyClass的成員變量 ,因為Person已經(jīng)加載過了,所以只執(zhí)行一遍,只需根據(jù)類的模板執(zhí)行其構(gòu)造方法,來復(fù)制成另外一個副本,此時打印person MyClass
最后執(zhí)行Myclass的構(gòu)造方法,打印myclass constructor
總結(jié):
非靜態(tài)代碼塊=>初始化成員變量=>非靜態(tài)代碼塊=>構(gòu)造器方法
感謝您的耐心閱讀,如果您發(fā)現(xiàn)文章中有一些沒表述清楚的,或者是不對的地方,請給我留言,你的鼓勵是作者寫作最大的動力,
如果您認(rèn)為本文質(zhì)量不錯,讀后覺得收獲很大,不妨小額贊助我一下,讓我更有動力繼續(xù)寫出高質(zhì)量的文章。
支付寶
微信
作 者 : @mousycoder
原文出處 : http://mousycoder.com/2015/10/12/thinking-of-interview-question-1/
創(chuàng)作時間:2015-7-1
更新時間:2015-10-14
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/64566.html
摘要:想必面試題刷的多的同學(xué)對下面這道題目不陌生,能夠立即回答出輸出個,可是你真的懂為什么嗎為什么是輸出為什么是輸出個這兩個問題在我腦邊縈繞。同步任務(wù)都好理解,一個執(zhí)行完執(zhí)行下一個。本文只是我對這道面試題的一點思考,有誤的地方望批評指正。 想必面試題刷的多的同學(xué)對下面這道題目不陌生,能夠立即回答出輸出10個10,可是你真的懂為什么嗎?為什么是輸出10?為什么是輸出10個10?這兩個問題在我腦...
摘要:直接開始題目是厲害了說句實話開發(fā)中誰寫成這樣保證會被打死。不過面試就是面試,有面試官的考量點。官方是這么說的。結(jié)果完美,不過小姐姐的意思是數(shù)組的方法會自動觸發(fā)數(shù)組的。 直接開始題目是 if(a==1 && a==2 && a==3){ alert(厲害了) } 說句實話開發(fā)中誰寫成這樣保證會被打死。 不過面試就是面試,有面試官的考量點。 我理解的點有兩個 1、隱式類型轉(zhuǎn)換 先說...
摘要:另一個問題,就是我下面要提及的作用域問題,我當(dāng)時思考的時間太久了這是回憶中的面試題實際略有差異,不糾結(jié)了說一下腳本的運行結(jié)果引用錯誤中給出的錯誤提示。 版權(quán)聲明:此文首發(fā)于我的簡書賬號人生還有多少個二十年,轉(zhuǎn)載請注明出處。 此處有幾百字嘮叨: 當(dāng)天,我早早起床,跨越上百公里,高德導(dǎo)航,路人指點,跌跌撞撞到達(dá)招聘會現(xiàn)場,當(dāng)時已是中午十二點半,吃了午餐(半瓶白開水),開始準(zhǔn)備投遞...
摘要:首先,我先去上搜索了的定義運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象的實例。 今天看到一道面試題,如下,問: 實例化 Person 過程中,Person返回什么(或者 p 等于什么)? function Person(name) { this.name = name return name; } let p = new Person(Tom); 說實...
摘要:由虛擬機生成并拋出,,屬于系統(tǒng)內(nèi)部錯誤或者資源耗盡等嚴(yán)重情況,屬于需要擔(dān)負(fù)的責(zé)任,這一類異常事件是無法恢復(fù)或者不可能捕獲的,將導(dǎo)致應(yīng)用程序中斷,但是自定義是可以捕獲的。 題目 showImg(http://img-storage.qiniudn.com/15-9-22/50608386.jpg); 答案:D 分析 Java 異常的結(jié)構(gòu)體系 showImg(http://img-stor...
摘要:下面我們來使用面向?qū)ο箢悎D這里就不再畫了首先面試題中所提到的我們都可以看成類,比如停車場是一個類吧,它里面的車位是一個類吧,攝像頭,屏幕。。。 以下是某場的一道面試題(大概): 1、一個停車場,車輛入場時,攝像頭記錄下車輛信息2、屏幕上顯示所接收的車輛的信息情況(車牌號)以及各層車位的車位余量3、停車場一共四層車位,其中的三層都為普通車位,還有一層為特殊車位(體現(xiàn)在停車計費價格上面的不...
閱讀 2022·2021-11-24 09:39
閱讀 1884·2019-08-30 15:55
閱讀 2177·2019-08-30 15:53
閱讀 576·2019-08-29 13:16
閱讀 991·2019-08-26 12:20
閱讀 2390·2019-08-26 11:58
閱讀 3155·2019-08-26 10:19
閱讀 3314·2019-08-23 18:31