1. 程式人生 > >如何準備BAT技術面試答案(上)——Java研發方向

如何準備BAT技術面試答案(上)——Java研發方向

轉載https://blog.csdn.net/a724888/article/details/61414066

 

1. 面向物件和麵向過程的區別

面向過程 
優點:效能比面向物件高,因為類呼叫時需要例項化,開銷比較大,比較消耗資源;比如微控制器、嵌入式開發Linux/Unix等一般採用面向過程開發,效能是最重要的因素。 
缺點:沒有面向物件易維護、易複用、易擴充套件 
面向物件 
優點:易維護、易複用、易擴充套件,由於面向物件有封裝、繼承、多型性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易於維護 
缺點:效能比面向過程低

2. Java的四個基本特性(抽象、封裝、繼承,多型)

抽象:就是把現實生活中的某一類東西提取出來,用程式程式碼表示,我們通常叫做類或者介面。抽象包括兩個方面:一個是資料抽象,一個是過程抽象。資料抽象也就是物件的屬性。過程抽象是物件的行為特徵。 
封裝:把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行封裝隱藏。封裝分為屬性的封裝和方法的封裝。 
繼承:是對有著共同特性的多類事物,進行再抽象成一個類。這個類就是多類事物的父類。父類的意義在於抽取多類事物的共性。 
多型:允許不同類的物件對同一訊息做出響應。方法的過載、類的覆蓋正體現了多型。

3. 過載和重寫的區別

過載:發生在同一個類中,方法名必須相同,引數型別不同、個數不同、順序不同,方法返回值和訪問修飾符可以不同,發生在編譯時。 
重寫:發生在父子類中,方法名、引數列表必須相同,返回值小於等於父類,丟擲的異常小於等於父類,訪問修飾符大於等於父類;如果父類方法訪問修飾符為private則子類中就不是重寫。

4. 構造器Constructor是否可被override

構造器不能被重寫,不能用static修飾構造器,只能用 public private protected這三個許可權修飾符,且不能有返回語句。

5. 訪問控制符public,protected,private,以及預設的區別

private只有在本類中才能訪問; 
public在任何地方都能訪問; 
protected在同包內的類及包外的子類能訪問; 
預設不寫在同包內能訪問。

6. 是否可以繼承String類

String類是final類故不可以繼承,一切由final修飾過的都不能繼承

7. String和StringBuffer、StringBuilder的區別

可變性: 
String類中使用字元陣列儲存字串,private final char value[],所以string物件是不可變的。 
StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字元陣列儲存字串,char[] value,這兩種物件都是可變的。 
執行緒安全性: 
String中的物件是不可變的,也就可以理解為常量,執行緒安全。 
AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對方法加了同步鎖或者對呼叫的方法加了同步鎖,所以是執行緒安全的。StringBuilder並沒有對方法進行加同步鎖,所以是非執行緒安全的。 
效能: 
每次對String 型別進行改變的時候,都會生成一個新的 String 物件,然後將指標指向新的 String 物件。StringBuffer每次都會對 StringBuffer 物件本身進行操作,而不是生成新的物件並改變物件引用。相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的效能提升,但卻要冒多執行緒不安全的風險。

8. hashCode和equals方法的關係

equals相等,hashcode必相等;hashcode相等,equals可能不相等。

9. 抽象類和介面的區別

語法層次: 
抽象類和介面分別給出了不同的語法定義 
設計層次: 
抽象層次不同,抽象類是對類抽象,而介面是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是介面卻是對類區域性(行為)進行抽象。 
跨域不同,抽象類所體現的是一種繼承關係,要想使得繼承關係合理,父類和派生類之間必須存在”is-a” 關係,即父類和派生類在概念本質上應該是相同的。對於介面則不然,並不要求介面的實現者和介面定義在概念本質上是一致的,僅僅是實現了介面定義的契約而已,”like-a”的關係。。 
設計層次不同,抽象類是自底向上抽象而來的,介面是自頂向下設計出來的。

10. 自動裝箱與拆箱

裝箱:將基本型別用它們對應的引用型別包裝起來; 
拆箱:將包裝型別轉換為基本資料型別; 
Java使用自動裝箱和拆箱機制,節省了常用數值的記憶體開銷和建立物件的開銷,提高了效率,由編譯器來完成,編譯器會在編譯期根據語法決定是否進行裝箱和拆箱動作。

11. 什麼是泛型、為什麼要使用以及泛型擦除

泛型,即“引數化型別”。 
建立集合時就指定集合元素的型別,該集合只能儲存其指定型別的元素,避免使用強制型別轉換。 
Java編譯器生成的位元組碼是不包涵泛型資訊的,泛型型別資訊將在編譯處理是被擦除,這個過程即型別擦除。 泛型擦除可以簡單的理解為將泛型java程式碼轉換為普通java程式碼,只不過編譯器更直接點,將泛型java程式碼直接轉換成普通java位元組碼。 
型別擦除的主要過程如下:

  • 將所有的泛型引數用其最左邊界(最頂級的父型別)型別替換。
  • 移除所有的型別引數。

12. Java中的集合類及關係圖

List和Set繼承自Collection介面。 
Set無序不允許元素重複。HashSet和TreeSet是兩個主要的實現類。 
List有序且允許元素重複。ArrayList、LinkedList和Vector是三個主要的實現類。 
Map也屬於集合系統,但和Collection介面沒關係。Map是key對value的對映集合,其中key列就是一個集合。key不能重複,但是value可以重複。 HashMap、TreeMap和Hashtable是三個主要的實現類。 
SortedSet和SortedMap介面對元素按指定規則排序,SortedMap是對key列進行排序。

13. HashMap實現原理

具體原理一句兩句也說不清楚,網路文章: 
http://zhangshixi.iteye.com/blog/672697 
http://www.admin10000.com/document/3322.html

14. HashTable實現原理

具體原理一句兩句也說不清楚,網路文章: 
http://www.cnblogs.com/skywang12345/p/3310887.html 
http://blog.csdn.net/chdjj/article/details/38581035

15. HashMap和HashTable區別

  • HashTable的方法前面都有synchronized來同步,是執行緒安全的;HashMap未經同步,是非執行緒安全的。
  • HashTable不允許null值(key和value都不可以) ;HashMap允許null值(key和value都可以)。
  • HashTable有一個contains(Object value)功能和containsValue(Object value)功能一樣。
  • HashTable使用Enumeration進行遍歷;HashMap使用Iterator進行遍歷。
  • HashTable中hash陣列預設大小是11,增加的方式是 old*2+1;HashMap中hash陣列的預設大小是16,而且一定是2的指數。
  • 雜湊值的使用不同,HashTable直接使用物件的hashCode; HashMap重新計算hash值,而且用與代替求模。

16. ArrayList和vector區別

  • ArrayList和 Vector都實現了List介面, 都是通過陣列實現的。
  • Vector是執行緒安全的,而ArrayList是非執行緒安全的。
  • List第一次建立的時候,會有一個初始大小,隨著不斷向List中增加元素,當 List 認為容量不夠的時候就會進行擴容。Vector預設情況下自動增長原來一倍的陣列長度,ArrayList增長原來的50%。

17. ArrayList和LinkedList區別及使用場景

  • ArrayList底層是用陣列實現的,可以認為ArrayList是一個可改變大小的陣列。隨著越來越多的元素被新增到ArrayList中,其規模是動態增加的。
  • LinkedList底層是通過雙向連結串列實現的, LinkedList和ArrayList相比,增刪的速度較快。但是查詢和修改值的速度較慢。同時,LinkedList還實現了Queue介面,所以他還提供了offer(), peek(), poll()等方法。
  • LinkedList更適合從中間插入或者刪除(連結串列的特性)。 ArrayList更適合檢索和在末尾插入或刪除(陣列的特性)。

18. Collection和Collections的區別

  • java.util.Collection 是一個集合介面。它提供了對集合物件進行基本操作的通用介面方法。Collection介面在Java 類庫中有很多具體的實現。Collection介面的意義是為各種具體的集合提供了最大化的統一操作方式。
  • java.util.Collections 是一個包裝類。它包含有各種有關集合操作的靜態多型方法。此類不能例項化,就像一個工具類,服務於Java的Collection框架。

19. Concurrenthashmap實現原理

具體原理一句兩句也說不清楚,網路文章: 
http://www.cnblogs.com/ITtangtang/p/3948786.html 
http://ifeve.com/concurrenthashmap/

20. Error、Exception區別

Error類和Exception類的父類都是throwable類,他們的區別是:

  • Error類一般是指與虛擬機器相關的問題,如系統崩潰,虛擬機器錯誤,記憶體空間不足,方法呼叫棧溢等。對於這類錯誤的導致的應用程式中斷,僅靠程式本身無法恢復和和預防,遇到這樣的錯誤,建議讓程式終止。
  • Exception類表示程式可以處理的異常,可以捕獲且可能恢復。遇到這類異常,應該儘可能處理異常,使程式恢復執行,而不應該隨意終止異常。

21.Unchecked Exception和Checked Exception,各列舉幾個

Unchecked Exception:

  • 指的是程式的瑕疵或邏輯錯誤,並且在執行時無法恢復。
  • 包括Error與RuntimeException及其子類,如:OutOfMemoryError, UndeclaredThrowableException,IllegalArgumentException,IllegalMonitorStateException, NullPointerException, IllegalStateException, IndexOutOfBoundsException等。
  • 語法上不需要宣告丟擲異常。

Checked Exception:

  • 代表程式不能直接控制的無效外界情況(如使用者輸入,資料庫問題,網路異常,檔案丟失等)
  • 除了Error和RuntimeException及其子類之外,如:ClassNotFoundException, NamingException, ServletException, SQLException, IOException等。
  • 需要try catch處理或throws宣告丟擲異常。

22. Java中如何實現代理機制(JDK、CGLIB)

  • JDK動態代理:代理類和目標類實現了共同的介面,用到InvocationHandler介面。
  • CGLIB動態代理:代理類是目標類的子類, 用到MethodInterceptor介面

23. 多執行緒的實現方式

繼承Thread類、實現Runnable介面、使用ExecutorService、Callable、Future實現有返回結果的多執行緒。

24. 執行緒的狀態轉換

一張圖讓你看懂JAVA執行緒間的狀態轉換

25. 如何停止一個執行緒

這個問題簡單總結不一定說的清,看一篇網路文章: 
http://www.cnblogs.com/greta/p/5624839.html

26. 什麼是執行緒安全

執行緒安全就是多執行緒訪問同一程式碼,不會產生不確定的結果。

27. 如何保證執行緒安全

  • 對非安全的程式碼進行加鎖控制;
  • 使用執行緒安全的類;
  • 多執行緒併發情況下,執行緒共享的變數改為方法級的區域性變數。

28. Synchronized如何使用

synchronized是Java中的關鍵字,是一種同步鎖。它修飾的物件有以下幾種:

  • 修飾一個程式碼塊,被修飾的程式碼塊稱為同步語句塊,其作用的範圍是大括號{}括起來的程式碼,作用的物件是呼叫這個程式碼塊的物件;
  • 修飾一個方法,被修飾的方法稱為同步方法,其作用的範圍是整個方法,作用的物件是呼叫這個方法的物件;
  • 修改一個靜態的方法,其作用的範圍是整個靜態方法,作用的物件是這個類的所有物件;
  • 修改一個類,其作用的範圍是synchronized後面括號括起來的部分,作用主的物件是這個類的所有物件。

29. synchronized和Lock的區別

主要相同點:Lock能完成synchronized所實現的所有功能 
主要不同點:Lock有比synchronized更精確的執行緒語義和更好的效能。Lock的鎖定是通過程式碼實現的,而synchronized是在JVM層面上實現的,synchronized會自動釋放鎖,而Lock一定要求程式設計師手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。Lock鎖的範圍有侷限性,塊範圍,而synchronized可以鎖住塊、物件、類。

30. 多執行緒如何進行資訊互動

  • void notify() 喚醒在此物件監視器上等待的單個執行緒。
  • void notifyAll() 喚醒在此物件監視器上等待的所有執行緒。
  • void wait() 導致當前的執行緒等待,直到其他執行緒呼叫此物件的notify()方法或notifyAll()方法。
  • void wait(long timeout) 導致當前的執行緒等待,直到其他執行緒呼叫此物件的notify()方法或notifyAll()方法,或者超過指定的時間量。
  • void wait(long timeout, int nanos) 導致當前的執行緒等待,直到其他執行緒呼叫此物件的notify()方法或notifyAll()方法,或者其他某個執行緒中斷當前執行緒,或者已超過某個實際時間量。

31. sleep和wait的區別(考察的方向是是否會釋放鎖)

sleep()方法是Thread類中方法,而wait()方法是Object類中的方法。 
sleep()方法導致了程式暫停執行指定的時間,讓出cpu該其他執行緒,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復執行狀態,在呼叫sleep()方法的過程中,執行緒不會釋放物件鎖。而當呼叫wait()方法的時候,執行緒會放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件呼叫notify()方法後本執行緒才進入物件鎖定池準備

32. 多執行緒與死鎖

死鎖是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。 
產生死鎖的原因:

  • 因為系統資源不足。
  • 程序執行推進的順序不合適。
  • 資源分配不當。

33. 如何才能產生死鎖

產生死鎖的四個必要條件:

  • 互斥條件:所謂互斥就是程序在某一時間內獨佔資源。
  • 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。
  • 不剝奪條件:程序已獲得資源,在末使用完之前,不能強行剝奪。
  • 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。

34. 死鎖的預防

打破產生死鎖的四個必要條件中的一個或幾個,保證系統不會進入死鎖狀態。

  • 打破互斥條件。即允許程序同時訪問某些資源。但是,有的資源是不允許被同時訪問的,像印表機等等,這是由資源本身的屬性所決定的。所以,這種辦法並無實用價值。
  • 打破佔有且申請條件。可以實行資源預先分配策略。即程序在執行前一次性地向系統申請它所需要的全部資源。如果某個程序所需的全部資源得不到滿足,則不分配任何資源,此程序暫不執行。只有當系統能夠滿足當前程序的全部資源需求時,才一次性地將所申請的資源全部分配給該程序。由於執行的程序已佔有了它所需的全部資源,所以不會發生佔有資源又申請資源的現象,因此不會發生死鎖。
  • 打破迴圈等待條件,實行資源有序分配策略。採用這種策略,即把資源事先分類編號,按號分配,使程序在申請,佔用資源時不會形成環路。所有程序對資源的請求必須嚴格按資源序號遞增的順序提出。程序佔用了小號資源,才能申請大號資源,就不會產生環路,從而預防了死鎖。

35. 什麼叫守護執行緒,用什麼方法實現守護執行緒

守護執行緒是為其他執行緒的執行提供服務的執行緒。 
setDaemon(boolean on)方法可以方便的設定執行緒的Daemon模式,true為守護模式,false為使用者模式。

36. Java執行緒池技術及原理

這個有點長,還是看一篇文章吧: 
http://www.importnew.com/19011.html 
http://www.cnblogs.com/dolphin0520/p/3932921.html

37. java併發包concurrent及常用的類

這個內容有點多,需要仔細看: 
併發包諸類概覽:http://www.raychase.net/1912 
執行緒池:http://www.cnblogs.com/dolphin0520/p/3932921.html 
鎖:http://www.cnblogs.com/dolphin0520/p/3923167.html 
集合:http://www.cnblogs.com/huangfox/archive/2012/08/16/2642666.html

38. volatile關鍵字

用volatile修飾的變數,執行緒在每次使用變數的時候,都會讀取變數修改後的最的值。volatile很容易被誤用,用來進行原子性操作。 
Java語言中的volatile變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是synchronized的一部分。鎖提供了兩種主要特性:互斥(mutual exclusion)和可見性(visibility)。互斥即一次只允許一個執行緒持有某個特定的鎖,因此可使用該特性實現對共享資料的協調訪問協議,這樣,一次就只有一個執行緒能夠使用該共享資料。可見性必須確保釋放鎖之前對共享資料做出的更改對於隨後獲得該鎖的另一個執行緒是可見的,如果沒有同步機制提供的這種可見性保證,執行緒看到的共享變數可能是修改前的值或不一致的值,這將引發許多嚴重問題。Volatile變數具有synchronized的可見性特性,但是不具備原子特性。這就是說執行緒能夠自動發現 volatile 變數的最新值。

要使volatile變數提供理想的執行緒安全,必須同時滿足下面兩個條件:對變數的寫操作不依賴於當前值;該變數沒有包含在具有其他變數的不變式中。 
第一個條件的限制使volatile變數不能用作執行緒安全計數器。雖然增量操作(x++)看上去類似一個單獨操作,實際上它是一個由讀取-修改-寫入操作序列組成的組合操作,必須以原子方式執行,而volatile不能提供必須的原子特性。實現正確的操作需要使 x 的值在操作期間保持不變,而 volatile 變數無法實現這點。 
每一個執行緒執行時都有一個執行緒棧,執行緒棧儲存了執行緒執行時候變數值資訊。當執行緒訪問某一個物件時候值的時候,首先通過物件的引用找到對應在堆記憶體的變數的值,然後把堆記憶體變數的具體值load到執行緒本地記憶體中,建立一個變數副本,之後執行緒就不再和物件在堆記憶體變數值有任何關係,而是直接修改副本變數的值,在修改完之後的某一個時刻(執行緒退出之前),自動把執行緒變數副本的值回寫到物件在堆中變數。這樣在堆中的物件的值就產生變化了。 
read and load 從主存複製變數到當前工作記憶體 
use and assign 執行程式碼,改變共享變數值 
store and write 用工作記憶體資料重新整理主存相關內容 
其中use and assign 可以多次出現,但是這一些操作並不是原子性,也就是 在read load之後,如果主記憶體count變數發生修改之後,執行緒工作記憶體中的值由於已經載入,不會產生對應的變化,所以計算出來的結果會和預期不一樣。

39. Java中的NIO,BIO,AIO分別是什麼

  • BIO:同步並阻塞,伺服器實現模式為一個連線一個執行緒,即客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要的執行緒開銷,當然可以通過執行緒池機制改善。BIO方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程式直觀簡單易理解。
  • NIO:同步非阻塞,伺服器實現模式為一個請求一個執行緒,即客戶端傳送的連線請求都會註冊到多路複用器上,多路複用器輪詢到連線有I/O請求時才啟動一個執行緒進行處理。NIO方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,併發侷限於應用中,程式設計比較複雜,JDK1.4開始支援。
  • AIO:非同步非阻塞,伺服器實現模式為一個有效請求一個執行緒,客戶端的I/O請求都是由OS先完成了再通知伺服器應用去啟動執行緒進行處理.AIO方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作,程式設計比較複雜,JDK7開始支援。

40. IO和NIO區別

  • IO是面向流的,NIO是面向緩衝區的。
  • IO的各種流是阻塞的,NIO是非阻塞模式。
  • Java NIO的選擇器允許一個單獨的執行緒來監視多個輸入通道,你可以註冊多個通道使用一個選擇器,然後使用一個單獨的執行緒來“選擇”通道:這些通道里已經有可以處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的執行緒很容易來管理多個通道。

41. 序列化與反序列化

把物件轉換為位元組序列的過程稱為物件的序列化。 
把位元組序列恢復為物件的過程稱為物件的反序列化。

物件的序列化主要有兩種用途:

  • 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;
  • 在網路上傳送物件的位元組序列。
  • 當兩個程序在進行遠端通訊時,彼此可以傳送各種型別的資料。無論是何種型別的資料,都會以二進位制序列的形式在網路上傳送。傳送方需要把這個Java物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為Java物件。

42. 常見的序列化協議有哪些

Protobuf, Thrift, Hessian, Kryo

43. 記憶體溢位和記憶體洩漏的區別

記憶體溢位是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory。 
記憶體洩漏是指分配出去的記憶體不再使用,但是無法回收。

44. Java記憶體模型及各個區域的OOM,如何重現OOM

這部分內容很重要,詳細閱讀《深入理解Java虛擬機器》,也可以詳細閱讀這篇網路文章http://hllvm.group.iteye.com/group/wiki/2857-JVM

45. 出現OOM如何解決

  • 可通過命令定期抓取heap dump或者啟動引數OOM時自動抓取heap dump檔案。
  • 通過對比多個heap dump,以及heap dump的內容,分析程式碼找出記憶體佔用最多的地方。
  • 分析佔用的記憶體物件,是否是因為錯誤導致的記憶體未及時釋放,或者資料過多導致的記憶體溢位。

46. 用什麼工具可以查出記憶體洩漏

  • Memory Analyzer-是一款開源的JAVA記憶體分析軟體,查詢記憶體洩漏,能容易找到大塊記憶體並驗證誰在一直佔用它,它是基於Eclipse RCP(Rich Client Platform),可以下載RCP的獨立版本或者Eclipse的外掛。
  • JProbe-分析Java的記憶體洩漏。
  • JProfiler-一個全功能的Java剖析工具,專用於分析J2SE和J2EE應用程式。它把CPU、執行緒和記憶體的剖析組合在一個強大的應用中,GUI可以找到效能瓶頸、抓出記憶體洩漏、並解決執行緒的問題。
  • JRockit-用來診斷Java記憶體洩漏並指出根本原因,專門針對Intel平臺並得到優化,能在Intel硬體上獲得最高的效能。
  • YourKit .NET & Java Profiling業界領先的Java和.NET程式效能分析工具。
  • AutomatedQA -AutomatedQA的獲獎產品performance profiling和memory debugging工具集的下一代替換產品,支援Microsoft, Borland, Intel, Compaq 和 GNU編譯器。可以為.NET和Windows程式生成全面細緻的報告,從而幫助您輕鬆隔離並排除程式碼中含有的效能問題和記憶體/資源洩露問題。支援.Net 1.0,1.1,2.0,3.0和Windows 32/64位應用程式。
  • Compuware DevPartner Java Edition-包含Java記憶體檢測,程式碼覆蓋率測試,程式碼效能測試,執行緒死鎖,分散式應用等幾大功能模組

47. Java記憶體管理及回收演算法

閱讀這篇文章:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html

48. Java類載入器及如何載入類(雙親委派)

閱讀文章:https://www.ibm.com/developerworks/cn/java/j-lo-classloader/(推薦) 
http://blog.csdn.net/zhoudaxia/article/details/35824249

49. xml解析方式

  • DOM(JAXP Crimson解析器)
  • SAX
  • JDOM
  • DOM4J

區別:

  • DOM4J效能最好,連Sun的JAXM也在用DOM4J。目前許多開源專案中大量採用DOM4J,例如大名鼎鼎的hibernate也用DOM4J來讀取XML配置檔案。如果不考慮可移植性,那就採用DOM4J.
  • JDOM和DOM在效能測試時表現不佳,在測試10M文件時記憶體溢位。在小文件情況下還值得考慮使用DOM和JDOM。雖然JDOM的開發者已經說明他們期望在正式發行版前專注效能問題,但是從效能觀點來看,它確實沒有值得推薦之處。另外,DOM仍是一個非常好的選擇。DOM實現廣泛應用於多種程式語言。它還是許多其它與XML相關的標準的基礎,因為它正式獲得W3C推薦(與基於非標準的Java模型相對),所以在某些型別的專案中可能也需要它(如在JavaScript中使用DOM)。
  • SAX表現較好,這要依賴於它特定的解析方式-事件驅動。一個SAX檢測即將到來的XML流,但並沒有載入到記憶體(當然當XML流被讀入時,會有部分文件暫時隱藏在記憶體中)。

50. Statement和PreparedStatement之間的區別

  • PreparedStatement是預編譯的,對於批量處理可以大大提高效率. 也叫JDBC儲存過程
  • 使用 Statement 物件。在對資料庫只執行一次性存取的時侯,用 Statement 物件進行處理。PreparedStatement 物件的開銷比Statement大,對於一次性操作並不會帶來額外的好處。
  • statement每次執行sql語句,相關資料庫都要執行sql語句的編譯,preparedstatement是預編譯得, preparedstatement支援批處理
  • 程式碼:
 
程式碼片段1:

String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";

stmt.executeUpdate(updateString);

 

程式碼片段2:

PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");

updateSales.setInt(1, 75);

updateSales.setString(2, "Colombian");

updateSales.executeUpdate();

片斷1的區別在於,後者使用了PreparedStatement物件,而前者是普通的Statement物件。PreparedStatement物件不僅包含了SQL語句,而且大多數情況下這個語句已經被預編譯過,因而當其執行時,只需DBMS執行SQL語句,而不必先編譯。當你需要執行Statement物件多次的時候,PreparedStatement物件將會大大降低執行時間,當然也加快了訪問資料庫的速度。 
這種轉換也給你帶來很大的便利,不必重複SQL語句的句法,而只需更改其中變數的值,便可重新執行SQL語句。選擇PreparedStatement物件與否,在於相同句法的SQL語句是否執行了多次,而且兩次之間的差別僅僅是變數的不同。如果僅僅執行了一次的話,它應該和普通的物件毫無差異,體現不出它預編譯的優越性。

  • 執行許多SQL語句的JDBC程式產生大量的Statement和PreparedStatement物件。通常認為PreparedStatement物件比Statement物件更有效,特別是如果帶有不同引數的同一SQL語句被多次執行的時候。PreparedStatement物件允許資料庫預編譯SQL語句,這樣在隨後的執行中可以節省時間並增加程式碼的可讀性。 
    然而,在Oracle環境中,開發人員實際上有更大的靈活性。當使用Statement或PreparedStatement物件時,Oracle資料庫會快取SQL語句以便以後使用。在一些情況下,由於驅動器自身需要額外的處理和在Java應用程式和Oracle伺服器間增加的網路活動,執行PreparedStatement物件實際上會花更長的時間。 
    然而,除了緩衝的問題之外,至少還有一個更好的原因使我們在企業應用程式中更喜歡使用PreparedStatement物件,那就是安全性。傳遞給PreparedStatement物件的引數可以被強制進行型別轉換,使開發人員可以確保在插入或查詢資料時與底層的資料庫格式匹配。 
    當處理公共Web站點上的使用者傳來的資料的時候,安全性的問題就變得極為重要。傳遞給PreparedStatement的字串引數會自動被驅動器忽略。最簡單的情況下,這就意味著當你的程式試著將字串“D’Angelo”插入到VARCHAR2中時,該語句將不會識別第一個“,”,從而導致悲慘的失敗。幾乎很少有必要建立你自己的字串忽略程式碼。在Web環境中,有惡意的使用者會利用那些設計不完善的、不能正確處理字串的應用程式。特別是在公共Web站點上,在沒有首先通過PreparedStatement物件處理的情況下,所有的使用者輸入都不應該傳遞給SQL語句。此外,在使用者有機會修改SQL語句的地方,如HTML的隱藏區域或一個查詢字串上,SQL語句都不應該被顯示出來。