1. 程式人生 > >中級Java軟體開發面試題以及答案

中級Java軟體開發面試題以及答案

1、談談對面向物件的理解;以及三大特徵;

       面向物件是基於萬物皆物件這個觀點. 把一個物件抽象成類,具體上就是把一個物件的靜態特徵和動態特徵抽象成屬性和方法,也就是把一類事物的演算法和資料結構封裝在一個類之中,程式就是多個物件和互相之間的通訊組成的。

比如把一個人看成一個物件,這個人就會有他的屬性和行為;他有手、腳、嘴巴等就是他的屬性,或者他會說話、會走路、會吃飯就是行為,同理我們也可以把這些都看成物件,所以一個物件是可以由多個物件組成的。

       面向物件具有封裝性、繼承性、多型性。封裝就是隱蔽了物件內部不需要暴露的細節,使得內部細節的變動跟外界脫離,只依靠介面進行通訊;即不用管這個方法是怎麼實現的,只要知道他可以實現這個功能。封裝性降低了程式設計的複雜性. 通過繼承使得新建一個類變得容易,一個類繼承了父類,則父類所有的非私有的方法和公用屬性可以被這個類所呼叫。 而繼承和實現介面所產生的多型,使得不同的類所產生的物件能夠對相同的訊息作出不同的反應,即在實現介面的情況下,同一個方法裡的行為不同,極大地提高了程式碼的通用性.。

       總之,面向物件的特性提高了大型程式的重用性和可維護性。

2、String、StringBuffer、StringBuilder的區別;

1. String物件是不可改變的。 
2. 如果要修改字串而不建立新的物件,則可以使用 StringBuilder 類。例如,當在一個迴圈中將許多字串連線在一起時,使用 StringBuilder 類可以提升效能。 
3. 由於 String 的值一旦建立就不能再修改,所以稱它是恆定的。看似能修改 String 的方法實際上只是返回一個包含修改內容的新 String。

4. StringBuffer可改變的Unicode字元序列,允許併發操作,是執行緒安全的。


5.  StringBuilder:可改變的Unicode字元序列操作同StringBuffer,只是不支援併發操作,非執行緒安全的 。
6. 不考慮執行緒安全前提下,StringBuilder效能最高,StringBuffer次之,String比較差。  為什麼StringBuffer的效能比String高?主要原因在於String類是不可變類,任何對String引用指向的字串作出的修改都會導致生成新的字串(物件),而對StringBuffer的修改則不會導致新物件的產生。
那麼為什麼StringBuilder的效能比StringBuffer的高呢?這則與執行緒安全有關。StringBuilder是執行緒非安全的。

3、HashMap、LinkedHashMap、TreeMap的區別;

HashMap,LinkedHashMap,TreeMap都屬於Map

Map 主要用於儲存鍵(key)值(value)對,根據鍵得到值,因此鍵不允許鍵重複,但允許值重複。

HashMap 是一個最常用的Map,它根據鍵的HashCode 值儲存資料,根據鍵可以直接獲取它的值,具有很快的訪問速度。HashMap最多隻允許一條記錄的鍵為Null;允許多條記錄的值為Null;HashMap不支援執行緒的同步,即任一時刻可以有多個執行緒同時寫HashMap;可能會導致資料的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。 LinkedHashMap 也是一個HashMap,但是內部維持了一個雙向連結串列,可以保持順序; TreeMap 不僅可以保持順序,而且可以用於排序; 詳細操作看文章……

4、ArrayList、LinkedList、vector 的區別;

一、同步性 
ArrayList,LinkedList是不同步的,而Vestor是同步的。所以如果不要求執行緒安全的話,可以使用ArrayList或LinkedList,可以節省為同步而耗費的開銷。但在多執行緒的情況下,就得使用Vector。當然,也可以通過一些辦法包裝ArrayList,LinkedList,使他們也達到同步,但效率可能會有所降低。 
二、資料增長 
從內部實現機制來講ArrayList和Vector都是使用Object的陣列形式來儲存的。

當你向這兩種型別中增加元素的時候,如果元素的數目超出了內部陣列的長度它們都需要擴充套件內部陣列的長度,Vector預設情況下自動增長原來一倍的陣列長度;

ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以要在集合中儲存大量的資料那麼使用Vector有一些優勢。

三、檢索、插入、刪除物件的效率 
ArrayList和Vector中,是用下標來檢索一個物件,或在集合的末尾插入、刪除一個物件的時間是一樣的。但是,如果在集合的其他位置增加或移除元素那麼花費的時間會呈線形增長。 
LinkedList中,在插入、刪除集合中任何位置的元素所花費的時間都是一樣的,但它在查詢一個元素的時候比較慢。 
一般大家都知道ArrayList和LinkedList的大致區別: 
     1.ArrayList是實現了基於動態陣列的資料結構,LinkedList基於連結串列的資料結構。 
     2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。 
    3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。

5、抽象類與介面(interface)的區別;

1.abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個interface。

  2.在abstract class 中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的不能被修改的資料成員(也就是必須是static final的,不過在 interface中一般不定義資料成員),所有的成員方法都是abstract的。

  3.abstract class和interface所反映出的設計理念不同。其實abstract class表示的是"is-a"關係,interface表示的是"like-a"關係。 

  4.實現抽象類和介面的類必須實現其中的所有方法。抽象類中可以有非抽象方法。介面中則不能有實現方法。

  5.介面中定義的變數預設是public static final 型,且必須給其初值,所以實現類中不能重新定義,也不能改變其值。

  6.抽象類中的變數預設是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。 

  7.介面中的方法預設都是 public,abstract 型別的。 

7、多執行緒是什麼?用什麼實現?

多執行緒是為了同步完成多項任務,不是為了提高執行效率,而是為了提高資源使用效率來提高系統的效率。執行緒是在同一時間需要完成多項任務的時候實現的。如:火車是一個程序,而車廂就是執行緒,車廂脫離了火車是不能開動的,同理可以由多個車廂,則一個程序是有多個執行緒來提高效率的。

在JAVA中,要開始一個執行緒,有兩種方式。一是直接呼叫Thread例項的start()方法,繼承Thread類;二是實現Runnable介面,將Runable例項傳給一個Thread例項然後呼叫它的start()方法。

實現同步也有兩種,一種是用同步方法,一種是用同步塊, 同步方法就是在方法返回型別後面加上synchronized, 比如:public void synchronized add(){...}同步塊就是直接寫:synchronized (這裡寫需要同步的物件){...}

8、概述一下SpringMVC的工作原理。

1、客戶端發出一個http請求給web伺服器,web伺服器對http請求進行解析,如果匹配DispatcherServlet的請求對映路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet.

2、DipatcherServlet接收到這個請求之後將根據請求的資訊(包括URL、Http方法、請求報文頭和請求引數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。

3-4、DispatcherServlet根據HandlerMapping找到對應的Handler,將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的HandlerAdapter對Handler進行具體的呼叫。

5、Handler對資料處理完成以後將返回一個ModelAndView()物件給DispatcherServlet。

6、Handler返回的ModelAndView()只是一個邏輯檢視並不是一個正式的檢視,DispatcherSevlet通過ViewResolver將邏輯檢視轉化為真正的檢視View。

7、Dispatcher通過model解析出ModelAndView()中的引數進行解析最終展現出完整的view並返回給客戶端。


9、關於Spring,IOC和AOP的概念;

spring 的優點?
1.降低了元件之間的耦合性 ,實現了軟體各層之間的解耦 
2.可以使用容易提供的眾多服務,如事務管理,訊息服務等 
3.容器提供單例模式支援 
4.容器提供了AOP技術,利用它很容易實現如許可權攔截,執行期監控等功能 
5.容器提供了眾多的輔助類,能加快應用的開發 
6.spring對於主流的應用框架提供了整合支援,如hibernate,JPA,Struts等 
7.spring屬於低侵入式設計,程式碼的汙染極低 
8.獨立於各種應用伺服器 
9.spring的DI機制降低了業務物件替換的複雜性 
10.Spring的高度開放性,並不強制應用完全依賴於Spring,開發者可以自由選擇spring的部分或全部 

什麼是DI機制? 
依賴注入(Dependecy Injection)和控制反轉(Inversion of Control)是同一個概念,具體的講:當某個角色 
需要另外一個角色協助的時候,在傳統的程式設計過程中,通常由呼叫者來建立被呼叫者的例項。但在spring中 
建立被呼叫者的工作不再由呼叫者來完成,因此稱為控制反轉。建立被呼叫者的工作由spring來完成,然後注入呼叫者 
因此也稱為依賴注入。 
spring以動態靈活的方式來管理物件 , 注入的兩種方式,設定注入和構造注入。 
設定注入的優點:直觀,自然 
構造注入的優點:可以在構造器中決定依賴關係的順序。 

什麼是AOP? 
面向切面程式設計(AOP)完善spring的依賴注入(DI),面向切面程式設計在spring中主要表現為兩個方面 
1.面向切面程式設計提供宣告式事務管理 
2.spring支援使用者自定義的切面 

面向切面程式設計(aop)是對面向物件程式設計(oop)的補充, 
面向物件程式設計將程式分解成各個層次的物件,面向切面程式設計將程式執行過程分解成各個切面。 
AOP從程式執行角度考慮程式的結構,提取業務處理過程的切面,oop是靜態的抽象,aop是動態的抽象, 
是對應用執行過程中的步驟進行抽象,,從而獲得步驟之間的邏輯劃分。 

aop框架具有的兩個特徵: 
1.各個步驟之間的良好隔離性 
2.原始碼無關性 

10、spring事務怎麼配置的。

第一種方式:每個Bean都有一個代理;

 第二種方式:所有Bean共享一個代理基類;

第三種方式:使用攔截器;

第四種方式:使用tx標籤配置的攔截器;

第五種方式:全註解;

詳細見文章……

11、Mybatis與hibernate的區別。

1. hibernate是全自動,而mybatis是半自動。

hibernate完全可以通過物件關係模型實現對資料庫的操作,擁有完整的JavaBean物件與資料庫的對映結構來自動生成sql。而mybatis僅有基本的欄位對映,物件資料以及物件實際關係仍然需要通過手寫sql來實現和管理。

2. hibernate資料庫移植性遠大於mybatis。

hibernate通過它強大的對映結構和hql語言,大大降低了物件與資料庫(oracle、mysql等)的耦合性,而mybatis由於需要手寫sql,因此與資料庫的耦合性直接取決於程式設計師寫sql的方法,如果sql不具通用性而用了很多某資料庫特性的sql語句的話,移植性也會隨之降低很多,成本很高。

3. hibernate擁有完整的日誌系統,mybatis則欠缺一些。

hibernate日誌系統非常健全,涉及廣泛,包括:sql記錄、關係異常、優化警告、快取提示、髒資料警告等;而mybatis則除了基本記錄功能外,功能薄弱很多。

4. mybatis相比hibernate需要關心很多細節

hibernate配置要比mybatis複雜的多,學習成本也比mybatis高。但也正因為mybatis使用簡單,才導致它要比hibernate關心很多技術細節。mybatis由於不用考慮很多細節,開發模式上與傳統jdbc區別很小,因此很容易上手並開發專案,但忽略細節會導致專案前期bug較多,因而開發出相對穩定的軟體很慢,而開發出軟體卻很快。hibernate則正好與之相反。但是如果使用hibernate很熟練的話,實際上開發效率絲毫不差於甚至超越mybatis。

5. sql直接優化上,mybatis要比hibernate方便很多

由於mybatis的sql都是寫在xml裡,因此優化sql比hibernate方便很多。而hibernate的sql很多都是自動生成的,無法直接維護sql;雖有hql,但功能還是不及sql強大,見到報表等變態需求時,hql也歇菜,也就是說hql是有侷限的;hibernate雖然也支援原生sql,但開發模式上卻與orm不同,需要轉換思維,因此使用上不是非常方便。總之寫sql的靈活度上hibernate不及mybatis。

12、Mybatis中怎麼呼叫儲存過程。

1.在資料庫中建立以下的儲存過程:

java程式碼:
  1. create or replace procedure pro_hello(p_user_name in varchar2,p_result out varchar2) is  
  2. begin  
  3.   p_result := 'hello,' || p_user_name;  
  4. end;  

2.編寫SQL對映檔案mapper.xml:

java程式碼:
  1. <select id="proHello" statementType="CALLABLE">  
  2. <![CDATA[  
  3.     {call pro_hello (#{p_user_name,mode=IN,jdbcType=VARCHAR},#{result,mode=OUT,jdbcType=VARCHAR})}  
  4. ]]>  
  5. </select>  

3.編寫JAVA程式碼呼叫儲存過程

java程式碼:
  1. publicclass ProcedureTest {  
  2.          publicstaticvoid main(String[] args) throws IOException {  
  3.             String resource = "mybatis.cfg.xml";  
  4.             Reader reader = Resources.getResourceAsReader(resource);  
  5.             SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);  
  6.             SqlSession session = ssf.openSession();  
  7.            try {  
  8.                  Map<String, String> param = new HashMap<String, String>();  
  9.                  param.put("p_user_name""zhangsan");  
  10.                  String returnValue = (String) session.selectOne("User.proHello", param);  
  11.                  System.out.println("message=" + param.get("p_user_name"));  
  12.                  System.out.println("result=" + param.get("result"));  
  13.                  System.out.println("returnValue=" + returnValue);  
  14.            } catch (Exception e) {  
  15.                 e.printStackTrace();  
  16.            } finally {  
  17.               session.close();  
  18.           }  
  19.        }  
  20. }  

13、儲存過程與函式的區別。

A:函式必須有返回值,而過程沒有. 
B:函式可以單獨執行.而過程必須通過execute執行. 
C:函式可以嵌入到SQL語句中執行.而過程不行. 
其實我們可以將比較複雜的查詢寫成函式.然後到儲存過程中去呼叫這些函式. 
Oracle中的函式與儲存過程的特點: 
A. 一般來說,儲存過程實現的功能要複雜一點,而函式的實現的功能針對性比較強。 
B.對於儲存過程來說可以返回引數,而函式只能返回值或者表物件。 
C.儲存過程一般是作為一個獨立的部分來執行,而函式可以作為查詢語句的一個部分來呼叫,由於函式可以返回一個表物件,因此它可以在查詢語句中位於FROM關鍵字的後面

14、資料庫的三大正規化。

1 第一正規化(1NF)
在任何一個關係資料庫中,第一正規化(1NF)是對關係模式的基本要求,不滿足第一正規化(1NF)的資料庫就不是關係資料庫。
所謂第一正規化(1NF)是指資料庫表的每一列都是不可分割的基本資料項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。如果出現重複的屬性,就可能需要定義一個新的實體,新的實體由重複的屬性構成,新實體與原實體之間為一對多關係。在第一正規化(1NF)中表的每一行只包含一個例項的資訊。例如,對於圖3-2 中的員工資訊表,不能將員工資訊都放在一列中顯示,也不能將其中的兩列或多列在一列中顯示;員工資訊表的每一行只表示一個員工的資訊,一個員工的資訊在表中只出現一次。簡而言之,第一正規化就是無重複的列。

2 第二正規化(2NF)
第二正規化(2NF)是在第一正規化(1NF)的基礎上建立起來的,即滿足第二正規化(2NF)必須先滿足第一正規化(1NF)。第二正規化(2NF)要求資料庫表中的每個例項或行必須可以被惟一地區分。為實現區分通常需要為表加上一個列,以儲存各個例項的惟一標識。如圖3-2 員工資訊表中加上了員工編號(emp_id)列,因為每個員工的員工編號是惟一的,因此每個員工可以被惟一區分。這個惟一屬性列被稱為主關鍵字或主鍵、主碼。
第二正規化(2NF)要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性,如果存在,那麼這個屬性和主關鍵字的這一部分應該分離出來形成一個新的實體,新實體與原實體之間是一對多的關係。為實現區分通常需要為表加上一個列,以儲存各個例項的惟一標識。簡而言之,第二正規化就是非主屬性非部分依賴於主關鍵字。

3 第三正規化(3NF)
滿足第三正規化(3NF)必須先滿足第二正規化(2NF)。簡而言之,第三正規化(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字資訊。例如,存在一個部門資訊表,其中每個部門有部門編號(dept_id)、部門名稱、部門簡介等資訊。那麼在圖3-2的員工資訊表中列出部門編號後就不能再將部門名稱、部門簡介等與部門有關的資訊再加入員工資訊表中。如果不存在部門資訊表,則根據第三正規化(3NF)也應該構建它,否則就會有大量的資料冗餘。簡而言之,第三正規化就是屬性不依賴於其它非主屬性。


15、sql優化有哪些?分別起了什麼作用?

1、IN 操作符

推薦方案:在業務密集的SQL當中儘量不採用IN操作符,用EXISTS 方案代替。

2、NOT IN操作符

此操作是強列不推薦使用的,因為它不能應用表的索引。推薦方案:用NOT EXISTS 方案代替

3、IS NULL 或 IS NOT NULL操作(判斷欄位是否為空)

判斷欄位是否為空一般是不會應用索引的,因為索引是不索引空值的。

推薦方案:用其它相同功能的操作運算代替,如:a is not null 改為 a>0 或a>’’等。不允許欄位為空,而用一個預設值代替空值,如申請中狀態欄位不允許為空,預設為申請。

4、LIKE操作符

LIKE操作符可以應用萬用字元查詢,裡面的萬用字元組合可能達到幾乎是任意的查詢,但是如果用得不好則會產生效能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。

一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,效能肯定大大提高。

5、UNION操作符

UNION在進行錶鏈接後會篩選掉重複的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄,最常見的是過程表與歷史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在執行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,如果表資料量大的話可能會導致用磁碟進行排序。

6、儘量將多條sql語句寫成一條sql語句來查詢

7、多表查詢用別名查詢

8、用索引提高效率