编程面试题之——简答题(持续更新...)
簡答題:
?
1、try{}里有一個return語句,那么緊跟在這個try后的finally{}里的代碼會不會被執(zhí)行,什么時候被執(zhí)行,在return前還是后?
答:會執(zhí)行,在方法返回調(diào)用者前執(zhí)行。
注意:在finally中改變返回值的做法是不好的,因為如果存在finally代碼塊,try中的return語句不會立馬返回調(diào)用者,而是記錄下返回值待finally代碼塊執(zhí)行完畢之后再向調(diào)用者返回其值,然后如果在finally中修改了返回值,就會返回修改后的值。
顯然,在finally中返回或者修改返回值會對程序造成很大的困擾
C#中直接用編譯錯誤的方式來阻止程序員干這種齷齪的事情
Java中也可以通過提升編譯器的語法檢查級別來產(chǎn)生警告或錯誤
Eclipse中可以在如圖所示的地方進行設(shè)置,強烈建議將此項設(shè)置為編譯錯誤。
2、Java語言如何進行異常處理,關(guān)鍵字:throws、throw、try、catch、finally分別如何使用?
答:Java通過面向?qū)ο蟮姆椒ㄟM行異常處理,把各種不同的異常進行分類,并提供了良好的接口。
在Java中,每個異常都是一個對象,它是Throwable類或其子類的實例。
當(dāng)一個方法出現(xiàn)異常后便拋出一個異常對象,該對象中包含有異常信息,調(diào)用這個對象的方法可以捕獲到這個異常并可以對其進行處理。
Java的異常處理是通過5個關(guān)鍵詞來實現(xiàn)的:try、catch、throw、throws和finally。
一般情況下是用try來執(zhí)行一段程序,如果系統(tǒng)會拋出(throw)一個異常對象,可以通過它的類型來捕獲(catch)它,或通過總是執(zhí)行代碼塊(finally)來處理;
try用來指定一塊預(yù)防所有異常的程序;
catch子句緊跟在try塊后面,用來指定你想要捕獲的異常的類型;
throw語句用來明確地拋出一個異常;
throws用來聲明一個方法可能拋出的各種異常(當(dāng)然聲明異常時允許無病呻吟);
finally為確保一段代碼不管發(fā)生什么異常狀況都要被執(zhí)行;
try語句可以嵌套,每當(dāng)遇到一個try語句,異常的結(jié)構(gòu)就會被放入異常棧中,直到所有的try語句都完成。
如果下一級的try語句沒有對某種異常進行處理,異常棧就會執(zhí)行出棧操作,直到遇到有處理這種異常的try語句或者最終將異常拋給JVM。
3、什么時候用斷言(assert)?
答:斷言在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語言中都支持這種機制。
一般來說,斷言用于保證程序最基本、關(guān)鍵的正確性。斷言檢查通常在開發(fā)和測試時開啟。
為了保證程序的執(zhí)行效率,在軟件發(fā)布后斷言檢查通常是關(guān)閉的。
斷言是一個包含布爾表達式的語句,在執(zhí)行這個語句時假定該表達式為true;如果表達式的值為false,那么系統(tǒng)會報告一個AssertionError。
斷言的使用如下面的代碼所示:
1.assert(a > 0); // throws an AssertionError if a <= 0
斷言可以有兩種形式:
assert Expression1;
assert Expression1 : Expression2 ;
Expression1 應(yīng)該總是產(chǎn)生一個布爾值。
Expression2 可以是得出一個值的任意表達式;這個值用于生成顯示更多調(diào)試信息的字符串消息。
要在運行時啟用斷言,可以在啟動JVM時使用-enableassertions或者-ea標記。要在運行時選擇禁用斷言,可以在啟動JVM時使用-da或者-disableassertions標記。
要在系統(tǒng)類中啟用或禁用斷言,可使用-esa或-dsa標記。
還可以在包的基礎(chǔ)上啟用或者禁用斷言。
注意:斷言不應(yīng)該以任何方式改變程序的狀態(tài)。簡單的說,如果希望在不滿足某些條件時阻止代碼的執(zhí)行,就可以考慮用斷言來阻止它。
4、Error和Exception有什么區(qū)別?
答:Error表示系統(tǒng)級的錯誤和程序不必處理的異常,是恢復(fù)不是不可能但很困難的情況下的一種嚴重問題;比如內(nèi)存溢出,不可能指望程序能處理這樣的情況;
Exception表示需要捕捉或者需要程序進行處理的異常,是一種設(shè)計或?qū)崿F(xiàn)問題;也就是說,它表示如果程序運行正常,從不會發(fā)生的情況。
面試題:2005年摩托羅拉的面試中曾經(jīng)問過這么一個問題
“If a process reports a stack overflow run-time error, what’s the most possible cause?”
給了四個選項
a. lack of memory;
b. write on an invalid memory space;
c. recursive function calling;
d. array index out of boundary.
Java程序在運行時也可能會遭遇StackOverflowError,這是一個無法恢復(fù)的錯誤,只能重新修改代碼了,這個面試題的答案是c。
如果寫了不能迅速收斂的遞歸,則很有可能引發(fā)棧溢出的錯誤,如下所示:
class StackOverflowErrorTest {
public static void main(String[] args) {
main(null);
}
}
提示:用遞歸編寫程序時一定要牢記兩點:
1. 遞歸公式;
2. 收斂條件(什么時候就不再繼續(xù)遞歸)。
?
5、打印昨天的當(dāng)前時刻。
import java.util.Calendar;class YesterdayCurrent {public static void main(String[] args){Calendar cal = Calendar.getInstance();cal.add(Calendar.DATE, -1);System.out.println(cal.getTime());} }?
在Java 8中,可以用下面的代碼實現(xiàn)相同的功能。
?
import java.time.LocalDateTime;class YesterdayCurrent {public static void main(String[] args) {LocalDateTime today = LocalDateTime.now();LocalDateTime yesterday = today.minusDays(1);System.out.println(yesterday);} }?
6、比較一下Java和JavaSciprt。
答:JavaScript 與Java是兩個公司開發(fā)的不同的兩個產(chǎn)品。
?Java 是原Sun Microsystems公司推出的面向?qū)ο蟮某绦蛟O(shè)計語言,特別適合于互聯(lián)網(wǎng)應(yīng)用程序開發(fā);
?而JavaScript是Netscape公司的產(chǎn)品,為了擴展Netscape瀏覽器的功能而開發(fā)的一種可以嵌入Web頁面中運行的基于對象和事件驅(qū)動的解釋性語言。
?JavaScript的前身是LiveScript;而Java的前身是Oak語言。
?下面對兩種語言間的異同作如下比較:
-
基于對象和面向?qū)ο?#xff1a;Java是一種真正的面向?qū)ο蟮恼Z言,即使是開發(fā)簡單的程序,必須設(shè)計對象;JavaScript是種腳本語言,它可以用來制作與網(wǎng)絡(luò)無關(guān)的,與用戶交互作用的復(fù)雜軟件。它是一種基于對象(Object-Based)和事件驅(qū)動(Event-Driven)的編程語言,因而它本身提供了非常豐富的內(nèi)部對象供設(shè)計人員使用。
-
解釋和編譯:Java的源代碼在執(zhí)行之前,必須經(jīng)過編譯。JavaScript是一種解釋性編程語言,其源代碼不需經(jīng)過編譯,由瀏覽器解釋執(zhí)行。(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術(shù)來提升JavaScript的運行效率)
-
強類型變量和類型弱變量:Java采用強類型變量檢查,即所有變量在編譯之前必須作聲明;JavaScript中變量是弱類型的,甚至在使用變量前可以不作聲明,JavaScript的解釋器在運行時檢查推斷其數(shù)據(jù)類型。
-
代碼格式不一樣。
補充:其實Java和JavaScript最重要的區(qū)別是一個是靜態(tài)語言,一個是動態(tài)語言。目前的編程語言的發(fā)展趨勢是函數(shù)式語言和動態(tài)語言。
?在Java中類(class)是一等公民,而JavaScript中函數(shù)(function)是一等公民,因此JavaScript支持函數(shù)式編程,可以使用Lambda函數(shù)和閉包(closure),當(dāng)然Java 8也開始支持函數(shù)式編程,提供了對Lambda表達式以及函數(shù)式接口的支持。
7、Thread類的sleep()方法和對象的wait()方法都可以讓線程暫停執(zhí)行,它們有什么區(qū)別?
答:
sleep()方法(休眠)是線程類(Thread)的靜態(tài)方法,調(diào)用此方法會讓當(dāng)前線程暫停執(zhí)行指定的時間,將執(zhí)行機會(CPU)讓給其他線程,但是對象的鎖依然保持,因此休眠時間結(jié)束后會自動恢復(fù)。
wait()是Object類的方法,調(diào)用對象的wait()方法導(dǎo)致當(dāng)前線程放棄對象的鎖(線程暫停執(zhí)行),進入對象的等待池(wait pool),只有調(diào)用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),如果線程重新獲得對象的鎖就可以進入就緒狀態(tài)。
補充:可能不少人對什么是進程,什么是線程還比較模糊,對于為什么需要多線程編程也不是特別理解。
簡單的說:進程是具有-一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,是操作系統(tǒng)進行資源分配和調(diào)度的一個獨立單位;線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,是比進程更小的能獨立運行的基本單位。
線程的劃分尺度小于進程,這使得多線程程序的并發(fā)性高;進程在執(zhí)行時通常擁有獨立的內(nèi)存單元,而線程之間可以共享內(nèi)存。
使用多線程的編程通常能夠帶來更好的性能和用戶體驗,但是多線程的程序?qū)τ谄渌绦蚴遣挥押玫?#xff0c;因為它可能占用了更多的CPU資源。
當(dāng)然,也不是線程越多,程序的性能就越好,因為線程之間的調(diào)度和切換也會浪費CPU時間。
時下很時髦的Node.js就采用了單線程異步I/O的工作模式。
?
8、線程的sleep()方法和yield()方法有什么區(qū)別?
答:
① sleep()方法給其他線程運行機會時不考慮線程的優(yōu)先級,因此會給低優(yōu)先級的線程以運行的機會;yield()方法只會給相同優(yōu)先級或更高優(yōu)先級的線程以運行的機會;
② 線程執(zhí)行sleep()方法后轉(zhuǎn)入阻塞(blocked)狀態(tài),而執(zhí)行yield()方法后轉(zhuǎn)入就緒(ready)狀態(tài);
③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;
④ sleep()方法比yield()方法(跟操作系統(tǒng)CPU調(diào)度相關(guān))具有更好的可移植性。
?
轉(zhuǎn)載于:https://www.cnblogs.com/Mus-Li/p/6734956.html
總結(jié)
以上是生活随笔為你收集整理的编程面试题之——简答题(持续更新...)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ABP文档翻译--值对象
- 下一篇: ThinkingInJava对this关