1. 程式人生 > >2018面試題(一)

2018面試題(一)

1、servlet執行流程

客戶端發出http請求,web伺服器將請求轉發到servlet容器,servlet容器解析url並根據web.xml找到相對應的servlet,並將requestresponse物件傳遞給找到的servletservlet根據request就可以知道是誰發出的請求,請求資訊及其他資訊,當servlet處理完業務邏輯後會將資訊放入到response並響應到客戶端。

2、springMVC的執行流程

springMVC是由dispatchservlet為核心的分層控制框架。首先客戶端發出一個請求web伺服器解析請求url並去匹配dispatchservlet的對映url,如果匹配上就將這個請求放入到

dispatchservletdispatchservlet根據mapping對映配置去尋找相對應的handel,然後把處理權交給找到的handelhandel封裝了處理業務邏輯的程式碼,當handel處理完後會返回一個邏輯檢視modelandviewdispatchservlet,此時的modelandview是一個邏輯檢視不是一個正式檢視,所以dispatchservlet會通過viewresource檢視資源去解析modelandview,然後將解析後的引數放到view中返回到客戶端並展現。

3、給定一個txt檔案,如何得到某字串出現的次數

File file = new File("E://test.txt");

InputStream is = new FileInputStream(file);

byte b[] = new byte[1024];

int a = is.read(b);

String str[] = new String(b,0,a).split("");

int count = 0;

for(int i = 0;i<str.length;i++){

if("a".equals(str[i]))count++;

}

System.out.println(count);

4、Java設計模式思想(單列模式,策略模式,觀察者模式,代理模式)

a) 單例模式:

1、單例類只能有一個例項。2、單例類必須自己建立自己的唯一例項。3、單例類必須給所有其他物件提供這一例項。

單例模式核心只需要new一個例項物件的模式,比如資料庫連線,線上人數等,一些網站上看到的線上人數統計就是通過單例模式實現的,把一個計時器存放在資料庫或者記憶體中,當有人登陸的時候取出來加一再放回去,有人退出登陸的時候取出來減一再放回去,但是當有兩個人同時登陸的時候,會同時取出計數器,同時加一,同時放回去,這樣的話資料就會錯誤,所以需要一個全域性變數的物件給全部人使用,只需要new出一個例項物件,這就是單例模式的應用,並且單例模式節省資源,因為它控制了例項物件的個數,並有利於

gc回收。

餓漢式在類建立的同時就已經建立好一個靜態的物件供系統使用,以後不再改變,所以天生是執行緒安全的。

//餓漢式單例類.在類初始化時,已經自行例項化   
public class Singleton1 {  
    private Singleton1() {}  
    private static final Singleton1 single = new Singleton1();  
    //靜態工廠方法   
    public static Singleton1 getInstance() {  
        return single;  
    }  
}  

b) 策略模式:

策略模式屬於物件的行為模式。其用意是針對一組演算法,將每一個演算法封裝到具有共同介面的獨立的類中,從而使得它們可以相互替換。策略模式使得演算法可以在不影響到客戶端的情況下發生變化

這個模式涉及到三個角色:

環境(Context)角色:持有一個Strategy的引用。

抽象策略(Strategy)角色:這是一個抽象角色,通常由一個介面或抽象類實現。此角色給出所有的具體策略類所需的介面。

具體策略(ConcreteStrategy)角色:包裝了相關的演算法或行為。


就是將幾個類中公共的方法提取到一個新的類中,從而使擴充套件更容易,保證程式碼的可移植性,可維護性強。比如有個需求是寫鴨子物件,鴨子有叫,飛,外形這三種方法,如果每個鴨子類都寫這三個方法會出現程式碼的冗餘,這時候我們可以把鴨子中的叫,飛,外形這三個方法提取出來,放到鴨父類中,讓每個鴨子都繼承這個鴨父類,重寫這三個方法,這樣封裝的程式碼可移植性強,當用戶提出新的需求比如鴨子會游泳,那麼對於我們oo程式設計師來講就非常簡單了我們只需要在鴨父類中加一個游泳的方法,讓會游泳的鴨子重寫游泳方法就可以了。

c) 工廠模式:

簡單的工廠模式主要是統一提供例項物件的引用,通過工廠模式介面獲取例項物件的引用。比如一個登陸功能,後端有三個類,controller類,interface類,實現介面的實現類。當客戶端發出一個請求,當請求傳到controller類中時,controller獲取介面的引用物件,而實現介面的實現類中封裝好了登陸的業務邏輯程式碼。當你需要加一個註冊需求的時候只需要在介面類中加一個註冊方法,實現類中實現方法,controller獲取介面的引用物件即可,不需要改動原來的程式碼,這種做法是的可拓展性強。

d)觀察者模式

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。這個主題物件在狀態上發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。

抽象主題(Subject)角色:抽象主題角色把所有對觀察者物件的引用儲存在一個聚集(比如ArrayList物件)裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者物件,抽象主題角色又叫做抽象被觀察者(Observable)角色。

具體主題(ConcreteSubject)角色:將有關狀態存入具體觀察者物件;在具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。具體主題角色又叫做具體被觀察者(Concrete Observable)角色。

抽象觀察者(Observer)角色:為所有的具體觀察者定義一個介面,在得到主題的通知時更新自己,這個介面叫做更新介面。

具體觀察者(ConcreteObserver)角色:儲存與主題的狀態自恰的狀態。具體觀察者角色實現抽象觀察者角色所要求的更新介面,以便使本身的狀態與主題的狀態 像協調。如果需要,具體觀察者角色可以保持一個指向具體主題物件的引用

e)代理模式

所謂代理模式是指客戶端並不直接呼叫實際的物件,而是通過呼叫代理,來間接的呼叫實際的物件。

一般是因為客戶端不想直接訪問實際的物件,或者訪問實際的物件存在困難,因此通過一個代理物件來完成間接的訪問。

代理模式可以有兩種實現的方式,一種是靜態代理類,另一種是各大框架都喜歡的動態代理。下面我們主要講解一下這兩種代理模式

5、氣泡排序

原理:比較兩個相鄰的元素,將值大的元素交換至右端。

思路:依次比較相鄰的兩個數,將小數放在前面,大數放在後面。即在第一趟:首先比較第1個和第2個數,將小數放前,大數放後。然後比較第2個數和第3個數,將小數放前,大數放後,如此繼續,直至比較最後兩個數,將小數放前,大數放後。重複第一趟步驟,直至全部排序完成。

public static void bubbleSort(int []arr) {
        for(int i =0;i<arr.length-1;i++) {
            for(int j=0;j<arr.length-i-1;j++) {//-1為了防止溢位
                if(arr[j]>arr[j+1]) {
                    int temp = arr[j];
                     
                    arr[j]=arr[j+1];
                     
                    arr[j+1]=temp;
            }
            }    
        }
    }

快速排序:

1.先從數列中取出一個數作為基準數。

2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。

3.再對左右區間重複第二步,直到各區間只有一個數。

public static void main(String []args){
        System.out.println("Hello World");
        int[] a = {12,20,5,16,15,1,30,45,23,9};
        int start = 0;
        int end = a.length-1;
        sort(a,start,end);
        for(int i = 0; i<a.length; i++){
             System.out.println(a[i]);
         }
        
     }
     
     public void sort(int[] a,int low,int high){
         int start = low;
         int end = high;
         int key = a[low];
         
         
         while(end>start){
             //從後往前比較
             while(end>start&&a[end]>=key)  //如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置,然後又從前往後比較
                 end--;
             if(a[end]<=key){
                 int temp = a[end];
                 a[end] = a[start];
                 a[start] = temp;
             }
             //從前往後比較
             while(end>start&&a[start]<=key)//如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
                start++;
             if(a[start]>=key){
                 int temp = a[start];
                 a[start] = a[end];
                 a[end] = temp;
             }
         //此時第一次迴圈比較結束,關鍵值的位置已經確定了。左邊的值都比關鍵值小,右邊的值都比關鍵值大,但是兩邊的順序還有可能是不一樣的,進行下面的遞迴呼叫
         }
         //遞迴
         if(start>low) sort(a,low,start-1);//左邊序列。第一個索引位置到關鍵值索引-1
         if(end<high) sort(a,end+1,high);//右邊序列。從關鍵值索引+1到最後一個
     }


二分查詢

二分查詢也稱折半查詢(Binary Search),它是一種效率較高的查詢方法。但是,折半查詢要求線性表必須採用順序儲存結構,而且表中元素按關鍵字有序排列

public static int ef(int a[], int tag) {
    int first = 0;
    int end = a.length;
    for (int i = 0; i < a.length; i++) {
        int middle = (first + end) / 2;
        if (tag == a[middle]) {
            return middle;
        }
        if (tag > a[middle]) {
            first = middle + 1;
        }
        if (tag < a[middle]) {
            end = middle - 1;
        }
    }
    return 0;
}

6、ajax的理解

 Ajax為非同步請求,即區域性刷新技術,在傳統的頁面中,使用者需要點選按鈕或者事件觸發請求,到重新整理頁面,而非同步技術為不需要點選即可觸發事件,這樣使得使用者體驗感增強,比如商城購物車的非同步載入,當你點選商品時無需請求後臺而直接動態修改引數。

9、父類與子類之間的呼叫順序(列印結果)

a) 父類靜態程式碼塊

b) 子類靜態程式碼塊

c) 父類構造方法

d) 子類構造方法

e) 子類普通方法

f) 重寫父類的方法,則列印重寫後的方法

10、內部類與外部類的呼叫

a) 內部類可以直接呼叫外部類包括private的成員變數,使用外部類引用的this.關鍵字呼叫即可

b) 而外部類呼叫內部類需要建立內部類物件

11、多執行緒

程序是系統進行資源分配和排程的一個獨立單位.

執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位

執行緒和程序一樣分為五個階段:建立、就緒、執行、阻塞、終止

執行緒的優先級別:每一個執行緒都有優先級別,有限級別高的可以先獲取CPU資源使該執行緒從就緒狀態轉為執行狀態。也可以自定義執行緒的有限級別

12、死鎖

死鎖是指兩個或兩個以上的程序在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去

死鎖產生的條件:互斥、請求和保持、不剝奪、環路等待

避免死鎖:加鎖順序(執行緒按照一定的順序加鎖)

                  加鎖時限(執行緒嘗試獲取鎖的時候加上一定的時限,超過時限則放棄對該鎖的請求,並釋放自己佔有的鎖)

                  死鎖檢測

13、對spring ioc的理解

物件由原來程式本身建立,變為了程式接收物件

程式設計師主要精力集中於業務實現

實現了service和dao的解耦工作,service層和dao層實現了分離,沒有直接依賴關係。

如果dao的實現發生變化,應用程式本身不用改變。

依賴:指bean物件建立物件於容器。bean物件的依賴資源

注入:指bean物件的依賴資源由容器來設定和裝配。

14、對spring AOP的理解

AOP(Aspect Oriented Programming),即面向切面程式設計。它利用一種稱為"橫切"的技術,將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為"Aspect",即切面。

便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性。

16、Arraylistlinkedlist的區別

都是實現list介面的列表,arraylist是基於陣列的資料結構,linkedlist是基於連結串列的資料結構,

當獲取特定元素時,ArrayList效率比較快,它通過陣列下標即可獲取,而linkedlist則需要移動指標。

當儲存元素與刪除元素時linkedlist效率較快,只需要將指標移動指定位置增加或者刪除即可,而arraylist需要移動資料。

18、資料庫優化

a) 選擇合適的欄位,比如郵箱欄位可以設為char6),儘量把欄位設定為notnull,這樣查詢的時候資料庫就不需要比較nullb) 使用關聯查詢( left join on)查詢代替子查詢

c) 使用union聯合查詢手動建立臨時表

d) 開啟事物,當資料庫執行多條語句出現錯誤時,事物會回滾,可以維護資料庫的完整性e) 使用外來鍵,事物可以維護資料的完整性但是它卻不能保證資料的關聯性,使用外來鍵可以保證資料的關聯性

f) 使用索引,索引是提高資料庫效能的常用方法,它可以令資料庫伺服器以比沒有索引快的多的速度檢索特定的行,特別是對於maxminorder by查詢時,效果更明顯

g) 優化的查詢語句,絕大多數情況下,使用索引可以提高查詢的速度,但如果sql語句使用不恰當的話,索引無法發揮它的特性。

19、Tomcat伺服器優化(記憶體,併發連線數,快取)

a) 記憶體優化:主要是對Tomcat啟動引數進行優化,我們可以在Tomcat啟動指令碼中修改它的最大記憶體數等等。

b) 執行緒數優化:Tomcat的併發連線引數,主要在Tomcat配置檔案中server.xml中配置,比如修改最小空閒連線執行緒數,用於提高系統處理效能等等。

c) 優化快取:開啟壓縮功能,修改引數,比如壓縮的輸出內容大小預設為2KB,可以適當的修改。

20、HTTP協議

Getpost的區別:傳送資料,get攜帶引數與訪問地址傳送,使用者可以看見,這的話資訊會不安全,導致資訊洩露。而post則將欄位與對應值封裝在實體中傳送,這個過程使用者是不可見的。Get傳遞引數有限制,而post無限制。

21、TCP/UDP協議

TCP/IP協議按照層次分為以下四層。應用層、傳輸層、網路層、資料鏈路層。

TCP(Transmission Control Protocol,傳輸控制協議)面向連線的協議,也就是說,在收發資料前,必須和對方建立可靠的連線。一個TCP連線必須要經過三次對話才能建立起來,其中的過程非常複雜,只簡單的描述下這三次對話的簡單過程:主機A向主機B發出連線請求資料包:我想給你發資料,可以嗎?,這是第一次對話;主機B向主機A傳送同意連線和要求同步(同步就是兩臺主機一個在傳送,一個在接收,協調工作)的資料包:可以,你什麼時候發?,這是第二次對話;主機A再發出一個數據包確認主機B的要求同步:我現在就發,你接著吧!,這是第三次對話。三次對話的目的是使資料包的傳送和接收同步,經過三次對話之後,主機A才向主機B正式傳送資料。

(1) UDP是一個非連線的協議,傳輸資料之前源端和終端不建立連線,當它想傳送時就簡單地去抓取來自應用程式的資料,並儘可能快地把它扔到網路上。在傳送端,UDP傳送資料的速度僅僅是受應用程式生成資料的速度、計算機的能力和傳輸頻寬的限制;在接收端,UDP把每個訊息段放在佇列中,應用程式每次從佇列中讀一個訊息段。

(2) 由於傳輸資料不建立連線,因此也就不需要維護連線狀態,包括收發狀態等,因此一臺服務機可同時向多個客戶機傳輸相同的訊息。

TCP/IP協議按照層次分為以下四層。應用層、傳輸層、網路層、資料鏈路層。

23、類載入的過程

遇到一個新的類時,首先會到方法區去找class檔案,如果沒有找到就會去硬碟中找class檔案,找到後會返回,將class檔案載入到方法區中,在類載入的時候,靜態成員變數會被分配到方法區的靜態區域,非靜態成員變數分配到非靜態區域,然後開始給靜態成員變數初始化,賦預設值,賦完預設值後,會根據靜態成員變數書寫的位置賦顯示值,然後執行靜態程式碼。當所有的靜態程式碼執行完,類載入才算完成。

27、事物的理解

事物具有原子性,一致性,永續性,隔離性

原子性:是指在一個事物中,要麼全部執行成功,要麼全部失敗回滾。

一致性:事物執行之前和執行之後都處於一致性狀態

永續性:事物多資料的操作是永久性

隔離性:當一個事物正在對資料進行操作時,另一個事物不可以對資料進行操作,也就是多個併發事物之間相互隔離。

28、Struts工作流程

客戶端發出一個請求到servlet容器

請求經過一些列過濾被filterdispatcher呼叫,filterdispatch通過actionMapper去找相對應的action

Actionmapper找到對應的action返回給filterdispatchdispatch把處理權交給actionproxy

Actionproxy通過配置檔案找到對應的action

Actionproxy建立一個actionIinvocation的例項處理業務邏輯

一旦action處理完畢,actioninvocation負責根據stuts.xml的配置找到對應的返回結果。返回結果通常是jsp頁面。