您好,登錄后才能下訂單哦!
之前的題目請看之前的文章
想要更多學習資料和面試題的,可以私信我哦,大家一起學習進步!
36、數組有沒有length()這個方法? String有沒有length()這個方法?
數組沒有length()這個方法,有length的屬性。String有有length()這個方法。
37、下面這條語句一共創建了多少個對象: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。
38、try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后?
也許你的答案是在return之前,但往更細地說,我的答案是在return中間執行,請看下面程序代碼的運行結果:
public class Test {
/**
* @param args add by zxx ,Dec 9, 2008
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Test().test());;
}
static int test()
{
int x = 1;
try
{
return x;
}
finally
{
++x;
}
}
}
---------執行結果 ---------
1
運行結果是1,為什么呢?主函數調用子函數并得到結果的過程,好比主函數準備一個空罐子,當子函數要返回結果時,先把結果放在罐子里,然后再將程序邏輯返回到主函數。所謂返回,就是子函數說,我不運行了,你主函數繼續運行吧,這沒什么結果可言,結果是在說這話之前放進罐子里的。
39、下面的程序代碼輸出的結果是多少?
public class smallT
{
public static void main(String args[])
{
smallT t = new smallT();
int b = t.get();
System.out.println(b);
}
public int get()
{
try
{
return 1 ;
}
finally
{
return 2 ;
}
}
}
返回的結果是2。
我可以通過下面一個例子程序來幫助我解釋這個答案,從下面例子的運行結果中可以發現,try中的return語句調用的函數先于finally中調用的函數執行,也就是說return語句先執行,finally語句后執行,所以,返回的結果是2。Return并不是讓函數馬上返回,而是return語句執行后,將把返回結果放置進函數棧中,此時函數并不是馬上返回,它要執行finally語句后才真正開始返回。
在講解答案時可以用下面的程序來幫助分析:
public class Test {
/**
* @param args add by zxx ,Dec 9, 2008
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Test().test());;
}
int test()
{
try
{
return func1();
}
finally
{
return func2();
}
}
int func1()
{
System.out.println("func1");
return 1;
}
int func2()
{
System.out.println("func2");
return 2;
}
}
-----------執行結果-----------------
func1
func2
2
結論:finally中的代碼比return 和break語句后執行
40、final, finally, finalize的區別。
final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
內部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼……
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。JVM不保證此方法總被調用
41、運行時異常與一般異常有何異同?
異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是并不要求必須聲明拋出未被捕獲的運行時異常。
42、error和exception有什么區別?
error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。 exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
43、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異常。
提示答題者:就按照三個級別去思考:虛擬機必須宕機的錯誤,程序可以死掉也可以不死掉的錯誤,程序不應該死掉的錯誤;
44、請寫出你最常見到的5個runtime exception。
這道題主要考你的代碼量到底多大,如果你長期寫代碼的,應該經常都看到過一些系統方面的異常,你不一定真要回答出5個具體的系統異常,但你要能夠說出什么是系統異常,以及幾個系統異常就可以了,當然,這些異常完全用其英文名稱來寫是最好的,如果實在寫不出,那就用中文吧,有總比沒有強!
所謂系統異常,就是…..,它們都是RuntimeException的子類,在jdk doc中查RuntimeException類,就可以看到其所有的子類列表,也就是看到了所有的系統異常。我比較有印象的系統異常有:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。
45、JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎?
46、java中有幾種方法可以實現一個線程?用什么關鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?
java5以前,有如下兩種:
第一種:
new Thread(){}.start();這表示調用Thread子類對象的run方法,new Thread(){}表示一個Thread的匿名子類的實例對象,子類加上run方法后的代碼如下:
new Thread(){
public void run(){
}
}.start();
第二種:
new Thread(new Runnable(){}).start();這表示調用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個Runnable的匿名子類的實例對象,runnable的子類加上run方法后的代碼如下:
new Thread(new Runnable(){
public void run(){
}
}
).start();
從java5開始,還有如下一些線程池創建多線程的方式:
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i++)
{
pool.execute(new Runable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){public void run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){public void run(){}});
有兩種實現方法,分別使用new Thread()和new Thread(runnable)形式,第一種直接調用thread的run方法,所以,我們往往使用Thread子類,即new SubThread()。第二種調用runnable的run方法。
有兩種實現方法,分別是繼承Thread類與實現Runnable接口
用synchronized關鍵字修飾同步方法
反對使用stop(),是因為它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處于一種不連貫狀態,那么其他線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。suspend()方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標志,指出線程應該活動還是掛起。若標志指出線程應該掛起,便用wait()命其進入等待狀態。若標志指出線程應當恢復,則用一個notify()重新啟動線程。
47、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的講解一定要配合例子代碼來說明,才顯得自己真明白。
package com.huawei.interview;
public class MultiThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(new Thread1()).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
//由于這里的Thread1和下面的Thread2內部run方法要用同一對象作為監視器,我們這里不能用this,因為在Thread2里面的this和這個Thread1的this不是同一個對象。我們用MultiThread.class這個字節碼對象,當前虛擬機里引用這個變量時,指向的都是同一個對象。
synchronized (MultiThread.class) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting");
try {
//釋放鎖有兩種方式,第一種方式是程序自然離開監視器的范圍,也就是離開了synchronized關鍵字管轄的代碼范圍,另一種方式就是在synchronized關鍵字管轄的代碼內部調用監視器對象的wait方法。這里,使用wait方法釋放鎖。
MultiThread.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread1 is going on...");
System.out.println("thread1 is being over!");
}
}
}
private static class Thread2 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (MultiThread.class) {
System.out.println("enter thread2...");
System.out.println("thread2 notify other thread can release wait status..");
//由于notify方法并不釋放鎖, 即使thread2調用下面的sleep方法休息了10毫秒,但thread1仍然不會執行,因為thread2沒有釋放鎖,所以Thread1無法得不到鎖。
MultiThread.class.notify();
System.out.println("thread2 is sleeping ten millisecond...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread2 is going on...");
System.out.println("thread2 is being over!");
}
}
}
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。