Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)
作者:egg
郵箱:xtfggef@gmail.com
微博:http://weibo.com/xtfggef
博客:http://blog.csdn.net/zhangerqing(轉載請說明出處)
這章我們還是接著上一章的,繼續整理。
1、數組有沒有length()這個方法? String有沒有length()這個方法??
數組沒有length()這個方法,有length的屬性。String有有length()這個方法。
2、下面這條語句一共創建了多少個對象:String s="a"+"b"+"c"+"d";
答:對于如下代碼:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一條語句打印的結果為false,第二條語句打印的結果為true,這說明javac編譯可以對字符串常量直接相加的表達式進行優化,不必要等到運行期去進行加法運算處理,而是在編譯時去掉其中的加號,直接將其編譯成一個這些常量相連的結果。題目中的第一行代碼被編譯器在編譯時優化后,相當于直接定義了一個”abcd”的字符串,所以,上面的代碼應該只創建了一個String對象。寫如下兩行代碼,
String s = "a" + "b" + "c" + "d";
System.out.println(s == "abcd"); ? ??
最終打印的結果應該為true。關于字符串更多的介紹,請看:深入解讀Java字符串 ?http://blog.csdn.net/zhangerqing/article/details/8093919?
3、try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后??
也許你的答案是在return之前,但往更細地說,我的答案是在return中間執行,請看下面程序代碼的運行結果:
---------執行結果?---------
1
運行結果是1,為什么呢?主函數調用子函數并得到結果的過程,好比主函數準備一個空罐子,當子函數要返回結果時,先把結果放在罐子里,然后再將程序邏輯返回到主函數。所謂返回,就是子函數說,我不運行了,你主函數繼續運行吧,這沒什么結果可言,結果是在說這話之前放進罐子里的。
4、下面的程序代碼輸出的結果是多少?
返回的結果是2。
我可以通過下面一個例子程序來幫助我解釋這個答案,從下面例子的運行結果中可以發現,try中的return語句調用的函數先于finally中調用的函數執行,也就是說return語句先執行,finally語句后執行,所以,返回的結果是2。Return并不是讓函數馬上返回,而是return語句執行后,將把返回結果放置進函數棧中,此時函數并不是馬上返回,它要執行finally語句后才真正開始返回。
在講解答案時可以用下面的程序來幫助分析:
-----------執行結果-----------------
func1
func2
2
結論:finally中的代碼比return?和break語句后執行
5、final, finally, finalize的區別
final?用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。?內部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼……
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。JVM不保證此方法總被調用
異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是并不要求必須聲明拋出未被捕獲的運行時異常。
error?表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。?exception?表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
8、Java中的異常處理機制的簡單原理和應用
異常是指java程序運行時(非編譯)所發生的非正常情況或錯誤,與現實生活中的事件很相似,現實生活中的事件可以包含事件發生的時間、地點、人物、情節等信息,可以用一個對象來表示,Java使用面向對象的方式來處理異常,它把程序中發生的每個異常也都分別封裝到一個對象來表示的,該對象中包含有異常的信息。
Java對異常進行了分類,不同類型的異常分別用不同的Java類表示,所有異常的根類為java.lang.Throwable,Throwable下面又派生了兩個子類:Error和Exception,Error?表示應用程序本身無法克服和恢復的一種嚴重問題,程序只有死的份了,例如,說內存溢出和線程死鎖等系統問題。Exception表示程序還能夠克服和恢復的問題,其中又分為系統異常和普通異常,系統異常是軟件本身缺陷所導致的問題,也就是軟件開發人員考慮不周所導致的問題,軟件使用者無法克服和恢復這種問題,但在這種問題下還可以讓軟件系統繼續運行或者讓軟件死掉,例如,數組腳本越界(ArrayIndexOutOfBoundsException),空指針異常(NullPointerException)、類轉換異常(ClassCastException);普通異常是運行環境的變化或異常所導致的問題,是用戶能夠克服的問題,例如,網絡斷線,硬盤空間不夠,發生這樣的異常后,程序不應該死掉。
java為系統異常和普通異常提供了不同的解決方案,編譯器強制普通異常必須try..catch處理或用throws聲明繼續拋給上層調用方法處理,所以普通異常也稱為checked異常,而系統異常可以處理也可以不處理,所以,編譯器不強制用try..catch處理或用throws聲明,所以系統異常也稱為unchecked異常。
提示答題者:就按照三個級別去思考:虛擬機必須宕機的錯誤,程序可以死掉也可以不死掉的錯誤,程序不應該死掉的錯誤;
9、請寫出你最常見到的5個runtime?exception
NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、ClassNotFoundException
更多可以參考本博關于異常的講解:Java中的異常:http://blog.csdn.net/zhangerqing/article/details/8248186
10、sleep() 和 wait() 有什么區別??
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控狀態依然保持,到時后會自動恢復。調用sleep不會釋放對象鎖。?wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。)?
sleep就是正在執行的線程主動讓出cpu,cpu去執行其他線程,在sleep指定的時間過后,cpu才會回到這個線程上繼續往下執行,如果當前線程進入了同步鎖,sleep方法并不會釋放鎖,即使當前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無法得到執行。wait是指在一個已經進入了同步鎖的線程內,讓自己暫時讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運行,只有其他線程調用了notify方法(notify并不釋放鎖,只是告訴調用過wait方法的線程可以去參與獲得鎖的競爭了,但不是馬上得到鎖,因為鎖還在別人手里,別人還沒釋放。如果notify方法后面的代碼還有很多,需要這些代碼執行完后才會釋放鎖,可以在notfiy方法后增加一個等待和一些代碼,看看效果),調用wait方法的線程就會解除wait狀態和程序可以再次得到鎖后繼續向下運行。對于wait的講解一定要配合例子代碼來說明,才顯得自己真明白。
11、啟動一個線程是用run()還是start()??
啟動一個線程是調用start()方法,使線程就緒狀態,以后可以被調度為運行狀態,一個線程必須關聯一些具體的執行代碼,run()方法是該線程所關聯的執行代碼。?
12、當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法??
分幾種情況:
? ? ?1.其他方法前是否加了synchronized關鍵字,如果沒加,則能。
? ? ?2.如果這個方法內部調用了wait,則可以進入其他synchronized方法。
? ? ?3.如果其他個方法都加了synchronized關鍵字,并且內部沒有調用wait,則不能。
? ? ?4.如果其他方法是static,它用的同步鎖是當前類的字節碼,與非靜態的方法不能同步,因為非靜態的方法用的是this。
13、線程的基本概念、線程的基本狀態以及狀態之間的關系?
一個程序中可以有多條執行線索同時執行,一個線程就是程序中的一條執行線索,每個線程上都關聯有要執行的代碼,即可以有多段程序代碼同時運行,每個程序至少都有一個線程,即main方法執行的那個線程。如果只是一個cpu,它怎么能夠同時執行多段程序呢?這是從宏觀上來看的,cpu一會執行a線索,一會執行b線索,切換時間很快,給人的感覺是a,b在同時執行,好比大家在同一個辦公室上網,只有一條鏈接到外部網線,其實,這條網線一會為a傳數據,一會為b傳數據,由于切換時間很短暫,所以,大家感覺都在同時上網。?
狀態:就緒,運行,synchronize阻塞,wait和sleep掛起,結束。wait必須在synchronized內部調用。
調用線程的start方法后線程進入就緒狀態,線程調度系統將就緒狀態的線程轉為運行狀態,遇到synchronized語句時,由運行狀態轉為阻塞,當synchronized獲得鎖后,由阻塞轉為運行,在這種情況可以調用wait方法轉為掛起狀態,當線程關聯的代碼執行完后,線程變為結束狀態。?
14、簡述synchronized和java.util.concurrent.locks.Lock的異同 ??
主要相同點:Lock能完成synchronized所實現的所有功能?
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。?
舉例說明(對下面的題用lock進行了改寫):
16、子線程循環10次,接著主線程循環100,接著又回到子線程循環10次,接著再回到主線程又循環100,如此循環50次,請寫出程序
這道題不用說了,去看我關于集合類的講解就能答好了:http://blog.csdn.net/zhangerqing/article/details/8122075
18、Collection框架中實現比較要實現什么接口
comparable/comparator
19、ArrayList和Vector的區別
這兩個類都實現了List接口(List接口繼承了Collection接口),他們都是有序集合,即存儲在這兩個集合中的元素的位置都是有順序的,相當于一種動態的數組,我們以后可以按位置索引號取出某個元素,,并且其中的數據是允許重復的,這是HashSet之類的集合的最大不同處,HashSet之類的集合不可以按索引號去檢索其中的元素,也不允許有重復的元素(本來題目問的與hashset沒有任何關系,但為了說清楚ArrayList與Vector的功能,我們使用對比方式,更有利于說明問題)。
接著才說ArrayList與Vector的區別,這主要包括兩個方面:. (1)同步性:
Vector是線程安全的,也就是說是它的方法之間是線程同步的,而ArrayList是線程序不安全的,它的方法之間是線程不同步的。如果只有一個線程會訪問到集合,那最好是使用ArrayList,因為它不考慮線程安全,效率會高些;如果有多個線程會訪問到集合,那最好是使用Vector,因為不需要我們自己再去考慮和編寫線程安全的代碼。
備注:對于Vector&ArrayList、Hashtable&HashMap,要記住線程安全的問題,記住Vector與Hashtable是舊的,是java一誕生就提供了的,它們是線程安全的,ArrayList與HashMap是java2時才提供的,它們是線程不安全的。所以,我們講課時先講老的。(2)數據增長:
ArrayList與Vector都有一個初始的容量大小,當存儲進它們里面的元素的個數超過了容量時,就需要增加ArrayList與Vector的存儲空間,每次要增加存儲空間時,不是只增加一個存儲單元,而是增加多個存儲單元,每次增加的存儲單元的個數在內存空間利用與程序效率之間要取得一定的平衡。Vector默認增長為原來兩倍,而ArrayList的增長策略在文檔中沒有明確規定(從源代碼看到的是增長為原來的1.5倍)。ArrayList與Vector都可以設置初始的空間大小,Vector還可以設置增長的空間大小,而ArrayList沒有提供設置增長空間的方法。
? ? 總結:即Vector增長原來的一倍,ArrayList增加原來的0.5倍。
20、HashMap和Hashtable的區別 &&?List 和 Map
去看我關于集合類的講解就能答好了:http://blog.csdn.net/zhangerqing/article/details/8122075
21、Collection 和 Collections的區別?
Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.?
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
22、Set里的元素是不能重復的,那么用什么方法來區分重復與否呢? 是用==還是equals()? 它們有何區別??
Set里的元素是不能重復的,元素重復與否是使用equals()方法進行判斷的。?
equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值。
去看我關于集合類的講解有很詳細的回答:http://blog.csdn.net/zhangerqing/article/details/8122075
23、說出一些常用的類,包,接口,請各舉5個?
這種弱智的問題,總會有人考,沒辦法,有人考,你就得會。
要讓人家感覺你對java ee開發很熟,所以,不能僅僅只列core java中的那些東西,要多列你在做ssh項目中涉及的那些東西。就寫你最近寫的那些程序中涉及的那些類。
常用的類:BufferedReader ?BufferedWriter ?FileReader ?FileWirter ?String ?Integer?
java.util.Date,System,Class,List,HashMap
常用的包:java.lang ? java.io ?java.util ?java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate
常用的接口:Remote ?List ?Map ?Document ?NodeList ,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession
24、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類??
字節流,字符流。字節流繼承于InputStream OutputStream,字符流繼承于InputStreamReader OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便
25、字節流與字符流的區別
要把一片二進制數據數據逐一輸出到某個設備中,或者從某個設備中逐一讀取一片二進制數據,不管輸入輸出設備是什么,我們要用統一的方式來完成這些操作,用一種抽象的方式進行描述,這個抽象描述方式起名為IO流,對應的抽象類為OutputStream和InputStream ,不同的實現類就代表不同的輸入和輸出設備,它們都是針對字節進行操作的。在應用中,經常要完全是字符的一段文本輸出去或讀進來,用字節流可以嗎?計算機中的一切最終都是二進制的字節形式存在。對于“中國”這些字符,首先要得到其對應的字節,然后將字節寫入到輸出流。讀取時,首先讀到的是字節,可是我們要把它顯示為字符,我們需要將字節轉換成字符。由于這樣的需求很廣泛,人家專門提供了字符流的包裝類。底層設備永遠只接受字節數據,有時候要寫字符串到底層設備,需要將字符串轉成字節再進行寫入。字符流是字節流的包裝,字符流則是直接接受字符串,它內部將串轉成字節,再寫入底層設備,這為我們向IO設別寫入或讀取字符串提供了一點點方便。字符向字節轉換時,要注意編碼的問題,因為字符串轉成字節數組,其實是轉成該字符的某種編碼的字節形式,讀取也是反之的道理。下面是一個小的案例:
26、什么是java序列化,如何實現java序列化?或者請解釋Serializable接口的作用
我們有時候將一個java對象變成字節流的形式傳出去或者從一個字節流中恢復成一個java對象,例如,要將java對象存儲到硬盤或者傳送給網絡上的其他計算機,這個過程我們可以自己寫代碼去把一個java對象變成某個格式的字節流再傳輸,但是,jre本身就提供了這種支持,我們可以調用OutputStream的writeObject方法來做,如果要讓java?幫我們做,要被傳輸的對象必須實現serializable接口,這樣,javac編譯時就會進行特殊處理,編譯的類才可以被writeObject方法操作,這就是所謂的序列化。需要被序列化的類必須實現Serializable接口,該接口是一個mini接口,其中沒有需要實現的方法,implements?Serializable只是為了標注該對象是可被序列化的。?
例如,在web開發中,如果對象被保存在了Session中,tomcat在重啟時要把Session對象序列化到硬盤,這個對象就必須實現Serializable接口。如果對象要經過分布式系統進行網絡傳輸或通過rmi等遠程調用,這就需要在網絡上傳輸對象,被傳輸的對象就必須實現Serializable接口。
27、GC是什么??為什么要有GC??
本博客關于垃圾回收的詳細介紹:http://blog.csdn.net/zhangerqing/article/details/8214365
28、什么時候用assert?
assertion(斷言)在軟件開發中是一種常用的調試方式,很多開發語言中都支持這種機制。在實現中,assertion就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經處于不正確的狀態下,assert將給出警告或退出。一般來說,assertion用于保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啟。為了提高性能,在軟件發布后,assertion檢查通常是關閉的。?
29、java中會存在內存泄漏嗎,請簡單描述?
所謂內存泄露就是指一個不再被程序使用的對象或變量一直被占據在內存中。java中有垃圾回收機制,它可以保證一對象不再被引用的時候,即對象編程了孤兒的時候,對象將自動被垃圾回收器從內存中清除掉。由于Java 使用有向圖的方式進行垃圾回收管理,可以消除引用循環的問題,例如有兩個對象,相互引用,只要它們和根進程不可達的,那么GC也是可以回收它們的,例如下面的代碼可以看到這種情況的內存回收:
java中的內存泄露的情況:長生命周期的對象持有短生命周期對象的引用就很可能發生內存泄露,盡管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內存泄露的發生場景,通俗地說,就是程序員可能創建了一個對象,以后一直不再使用這個對象,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的,這就是java中可能出現內存泄露的情況,例如,緩存系統,我們加載了一個對象放在緩存中(例如放在一個全局map對象中),然后一直不再使用它,這個對象一直被緩存引用,但卻不再被使用。檢查java中的內存泄露,一定要讓程序將各種分支情況都完整執行到程序結束,然后看某個對象是否被使用過,如果沒有,則才能判定這個對象屬于內存泄露。如果一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄露。下面內容來自于網上(主要特點就是清空堆棧中的某個元素,并不是徹底把它從數組中拿掉,而是把存儲的總數減少,本人寫得可以比這個好,在拿掉某個元素時,順便也讓它從數組中消失,將那個元素所在的位置的值設置為null即可):我實在想不到比那個堆棧更經典的例子了,以致于我還要引用別人的例子,下面的例子不是我想到的,是書上看到的,當然如果沒有在書上看到,可能過一段時間我自己也想的到,可是那時我說是我自己想到的也沒有人相信的。
30、
作者:egg
郵箱:xtfggef@gmail.com
微博:http://weibo.com/xtfggef
博客:http://blog.csdn.net/zhangerqing(轉載請說明出處)
大家有什么補充的,在下面回復,同時也希望提出寶貴的意見!
題目和答案有些來自網絡和傳智播客張孝祥老師的整理,本人收集的,如果有回答不恰當的地方,還望及時指出、改正!
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java面试宝典系列之基础面试题Stri
- 下一篇: Java面试宝典系列之基础面试题Stri