今天面試題總結

一、final,finally,finalize的區別

1、性質不一樣html

(1)final爲關鍵字;java

(2)finalize()爲方法;ios

(3)finally爲爲區塊標誌,用於try語句中;編程

2、做用服務器

(1)final爲用於標識常量的關鍵字,final標識的關鍵字存儲在常量池中(在這裏final常量的具體用法將在下面進行介紹);架構

(2)finalize()方法在Object中進行了定義,用於在對象「消失」時,由JVM進行調用用於對對象進行垃圾回收,相似於C++中的析構函數;用戶自定義時,用於釋放對象佔用的資源(好比進行I/0操做);併發

(3)finally{}用於標識代碼塊,與try{}進行配合,不論try中的代碼執行完或沒有執行完(這裏指有異常),該代碼塊之中的程序一定會進行;函數式編程

3、final詳解函數

1定義變量高併發

1.1  final定義基本類型變量時,要求變量初始化必須在聲明時或者構造函數中,不能用於其它地方。該關鍵字定義的常量,除了初始化階段,不能更改常量的值。

1.2  final定義對象的引用,該引用的初始化與定義常量時的要求一致;該關鍵字定義的對象內容能夠改變,可是引用指向的地址不能改變;

2定義參數

若是傳入該參數定義的變量時,方法不能對該參數內容進行修改(錯誤),與定義變量的修改規則相同;java方法中傳遞基本類型時是傳值的,java方法對於對象的傳遞是傳參的;<歸根結底,java中方法的傳遞是依靠傳遞「副本」:對於基本類型,首先創建一個Copy,並將傳入的值賦值給Copy,而後對Copy進行操做;對於對象類型,首先創建一個引用Copy,並將傳入的對象引用賦值給Copy>

好比:method(final int test);

有些書上說,這裏final定義參數,尤爲是對象的參數頗有做用,不能在方法內對於對象的內容進行改變,這樣的說法是錯誤的!原來我也認爲這樣有些函數式編程的特色,不能對於對象的內容進行修改該,這裏依舊能夠對對象的內容進行修改。

??定義該參數有什麼用??

String天生就是final類型的!

3定義方法

(1)使用final關鍵字定義的方法,不能被子類繼承;

(2)容許編譯器將全部對此方法的調用轉化爲inline(行內)行爲,便可以將此方法直接複製在調用處,而不是進行例行的方法調用(保存斷點、壓棧),這樣會使程序的效率升高。可是---------若是過多的話,這樣會形成代碼膨脹,反而會影響效率,因此該方法要慎用。。

4定義類

一個任何final類沒法被任何人繼承,這也就意味着此類在一個繼承樹中是一個葉子類,而且此類被認爲是很完美的,不須要進行任何修改(總之是不推薦使用)

二、 有return的狀況下try catch finally的執行順序

結論:

一、無論有木有出現異常,finally塊中代碼都會執行;
二、當try和catch中有return時,finally仍然會執行;
三、finally是在return後面的表達式運算後執行的(此時並無返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麼樣,返回的值都不會改變,任然是以前保存的值),因此函數返回值是在finally執行前肯定的;
四、finally中最好不要包含return,不然程序會提早退出,返回值不是try或catch中保存的返回值。
舉例:
狀況1:try{} catch(){}finally{} return;
            顯然程序按順序執行。
狀況2:try{ return; }catch(){} finally{} return;
          程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
         再執行finally塊,最後執行try中return;
         finally塊以後的語句return,由於程序在try中已經return因此再也不執行。
狀況3:try{ } catch(){return;} finally{} return;
         程序先執行try,若是遇到異常執行catch塊,
         有異常:則執行catch中return以前(包括return語句中的表達式運算)代碼,再執行finally語句中所有代碼,
                     最後執行catch塊中return. finally以後也就是4處的代碼再也不執行。
         無異常:執行完try再finally再return.
狀況4:try{ return; }catch(){} finally{return;}
          程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
          再執行finally塊,由於finally塊中有return因此提早退出。
狀況5:try{} catch(){return;}finally{return;}
          程序執行catch塊中return以前(包括return語句中的表達式運算)代碼;
          再執行finally塊,由於finally塊中有return因此提早退出。
狀況6:try{ return;}catch(){return;} finally{return;}
          程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
          有異常:執行catch塊中return以前(包括return語句中的表達式運算)代碼;
                       則再執行finally塊,由於finally塊中有return因此提早退出。
          無異常:則再執行finally塊,由於finally塊中有return因此提早退出。

最終結論:任何執行try 或者catch中的return語句以前,都會先執行finally語句,若是finally存在的話。
                  若是finally中有return語句,那麼程序就return了,因此finally中的return是必定會被return的,
                  編譯器把finally中的return實現爲一個warning。

下面是個測試程序 public class FinallyTest { public static void main(String[] args) { System.out.println(new FinallyTest().test());; } static int test() { int x = 1; try { x++; return x; } finally { ++x; } } } 結果是2。

分析:

在try語句中,在執行return語句時,要返回的結果已經準備好了,就在此時,程序轉到finally執行了。 在轉去以前,try中先把要返回的結果存放到不一樣於x的局部變量中去,執行完finally以後,在從中取出返回結果, 所以,即便finally中對變量x進行了改變,可是不會影響返回結果。 它應該使用棧保存返回值。

三、單鏈表查找倒數第k個節點

題目:輸入一個單向鏈表,輸出該鏈表中倒數第k個結點。鏈表的倒數第0個結點爲鏈表的尾指針。

分析:爲了獲得倒數第k個結點,很天然的想法是先走到鏈表的尾端,再從尾端回溯k步。但是輸入的是單向鏈表,只有從前日後的指針而沒有從後往前的指針。所以咱們須要打開咱們的思路。既然不能從尾結點開始遍歷這個鏈表,咱們仍是把思路回到頭結點上來。假設整個鏈表有n個結點,那麼倒數第k個結點是從頭結點開始的第n-k-1個結點(從0開始計數)。若是咱們可以獲得鏈表中結點的個數n,那咱們只要從頭結點開始日後走n-k-1步就能夠了。如何獲得結點數n?這個不難,只須要從頭開始遍歷鏈表,每通過一個結點,計數器加一就好了。這種思路的時間複雜度是O(n),但須要遍歷鏈表兩次。第一次獲得鏈表中結點個數n,第二次獲得從頭結點開始的第n­-k-1個結點即倒數第k個結點。如 果鏈表的結點數很少,這是一種很好的方法。但若是輸入的鏈表的結點個數不少,有可能不能一次性把整個鏈表都從硬盤讀入物理內存,那麼遍歷兩遍意味着一個結 點須要兩次從硬盤讀入到物理內存。咱們知道把數據從硬盤讀入到內存是很是耗時間的操做。咱們能不能把鏈表遍歷的次數減小到1?若是能夠,將能有效地提升代碼執行的時間效率。若是咱們在遍歷時維持兩個指針,第一個指針從鏈表的頭指針開始遍歷,在第k-1步以前,第二個指針保持不動;在第k-1步開始,第二個指針也開始從鏈表的頭指針開始遍歷。因爲兩個指針的距離保持在k-1,當第一個(走在前面的)指針到達鏈表的尾結點時,第二個指針(走在後面的)指針正好是倒數第k個結點。這種思路只須要遍歷鏈表一次。對於很長的鏈表,只須要把每一個結點從硬盤導入到內存一次。所以這一方法的時間效率前面的方法要高。

 

#include <iostream>
#include <map>
using  namespace  std;
typedef  struct  ListNode{
     int  m_nkey;
     ListNode *m_pnext;
} ListNode,*Node;
int  main()
{
     int  n,k;
     cout<< "The length of the list: " <<endl;
     cin>>n;
     cout<< "Which one to select(from tail): " <<endl;
     cin>>k;
     Node head,tmp,last;
     for ( int  i=n;i>=1;i--)
     {
         tmp= new  ListNode();
         tmp->m_nkey=i;
         if (i==n)
         head=tmp;
         else
         last->m_pnext=tmp;
     tmp->m_pnext=NULL;
     last=tmp;
     }
     Node p=head;
     Node q=head;
     int  i=1;
     while (p!=NULL)
     {
         if (i<=k)
         {
             i++;
             p=p->m_pnext;
         }
         else
         {
             p=p->m_pnext;
             q=q->m_pnext;
         }
     }
     cout<< "The data is: " <<q->m_nkey<<endl;
}

四、如何實現大型系統的高併發性

高併發高負載的大型網站系統架構:http://developer.51cto.com/art/200906/129475.htm

高性能高併發服務器架構:http://www.doc88.com/p-5820457828.html

相關文章
相關標籤/搜索