撩課-Java面試題合輯50-100題
摘要:
50.如何將一個字串轉換為arraylist?
string 轉 ArrayList
先將字串按照某個字元切割,轉為string陣列
然後用Arrays的asList方法,將陣列轉為List
public class test1 {
public static void main(...
50.如何將一個字串轉換為arraylist?
string 轉 ArrayList 先將字串按照某個字元切割,轉為string陣列 然後用Arrays的asList方法,將陣列轉為List public class test1 { public static void main(String[] args){ //string 轉 ArrayList String str1 = "a,b,c"; ArrayList<String> list = new ArrayList<String>(Arrays.asList(str1.split(","))); System.out.println(list); } } ArrayList 轉 string public class test1 { public static void main(String[] args){ //ArrayList 轉 string ArrayList<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); System.out.println(list);//[a, b, c] String list_str = StringUtils.join(list,","); System.out.println(list_str);//a,b,c } }
51.HashMap的實現原理
HashMap的主幹是一個Entry陣列。 Entry是HashMap的基本組成單元, 每一個Entry包含一個key-value鍵值對。 HashMap基於hashing原理, 我們通過put()和get()方法儲存和獲取物件。 當我們將鍵值對傳遞給put()方法時, 它呼叫鍵物件的hashCode()方法 來計算hashcode, 讓後找到bucket位置來儲存值物件。 當獲取物件時, 通過鍵物件的equals()方法 找到正確的鍵值對, 然後返回值物件。 HashMap使用連結串列來解決碰撞問題, 當發生碰撞了, 物件將會儲存在連結串列的下一個節點中。 HashMap在每個連結串列節點中儲存鍵值對物件。 當兩個不同的鍵物件的hashcode 相同時會發生什麼? 它們會儲存在同一個bucket位置的連結串列中。 鍵物件的equals()方法用來找到鍵值對。 因為HashMap的好處非常多, 我曾經在電子商務的應用中使用HashMap作為快取。 因為金融領域非常多的運用Java, 也出於效能的考慮, 我們會經常用到HashMap和ConcurrentHashMap。 HashMap由陣列+連結串列組成的, 陣列是HashMap的主體, 連結串列則是主要為了解決雜湊衝突而存在的, 如果定位到的陣列位置不含連結串列 當前entry的next指向null, 那麼對於查詢, 新增等操作很快, 僅需一次定址即可; 如果定位到的陣列包含連結串列, 對於新增操作, 其時間複雜度為O(n), 首先遍歷連結串列, 存在即覆蓋, 否則新增; 對於查詢操作來講, 仍需遍歷連結串列, 然後通過key物件的equals方法逐一比對查詢。 所以,效能考慮,HashMap中的連結串列出現越少, 效能才會越好。
52.List、Set、Map之間的區別
List、Set是實現了Collection介面的子介面; 而Map是另一個集合介面。 1元素重複性: List允許有重複的元素。 任何數量的重複元素 都可以在不影響現有重複元素的值 及其索引的情況下插入到List集合中; Set集合不允許元素重複。 Set以及所有實現了Set介面的類 都不允許重複值的插入, 若多次插入同一個元素時, 在該集合中只顯示一個; Map以鍵值對的形式對元素進行儲存。 Map不允許有重複鍵, 但允許有不同鍵對應的重複的值; 2.元素的有序性: List及其所有實現類保持了 每個元素的插入順序; Set中的元素都是無序的; 但是某些Set的實現類 以某種殊形式對其中的元素進行排序, 如:LinkedHashSet按照元素的 插入順序進行排序; Map跟Set一樣對元素進行無序儲存, 但其某些實現類對元素進行了排序。 如:TreeMap根據鍵對其中的元素進行升序排序; 3.元素是否為空值: 1.List允許任意數量的空值; 2.Set最多允許一個空值的出現; 當向Set集合中新增多個null值時, 在該Set集合中只會顯示一個null元素 3.Map只允許出現一個空鍵, 但允許出現任意數量的空值; --------------------------------- 總結: List中的元素: 有序、可重複、可為空; Set中的元素: 無序、不重複、只有一個空元素; Map中的元素: 無序、鍵不重,值可重、可一個空鍵、多可空值;
53.HashMap 的長度為什麼是2的冪次方
1.減小雜湊衝突概率 假如當前Entry陣列長度為len, 插入節點時, 需要對key的hashcode進行二次雜湊, 然後跟len-1相與 得到的值一定小於len,避免陣列越界 如果len是2的N次方, 那麼len-1的後N位二進位制一定是全1 假設有兩個key, 他們的hashcode不同, 分別為code1和code2 code1和code2分別與一個後N位全1的二進位制相與, 結果一定也不同 但是,如果code1和code2分別 與一個後N位非全1的二進位制相與, 結果有可能相同 也就是說, 如果len是2^N, 不同hashcode的key 計算出來的陣列下標一定不同; 否則, 不同hashcode的key 計算出來的陣列下標一定相同。 所以HashMap長度為全1, 可以減小雜湊衝突概率。 ---------------------- 2.提高計算下標的效率 如果len的二進位制後n位非全1, 與len-1相與時, 0與1相與需要取反。 如果len的二進位制後n位全1, 完全不需要取反。 如果len為2^N, 那麼與len-1相與, 跟取餘len等價, 而與運算效率高於取餘。 如果len不是2^N, 與len-1相與, 跟取餘len不等價。
54.集合框架中的泛型有什麼優點?
首先, 瞭解一下Java關於泛型的概念。 泛型,在C++中被稱為模板, 就是一種抽象的程式設計方式。 當我們定義類和方法的時候, 可以用一種通用的方式進行定義, 而不必寫出具體的類, 這些未知的東西會在真正使用的時候在確定。 對於集合類來說, 它們可以存放各種型別的元素。 如果在存放之前, 就能確定元素的型別, 那麼就可以更加直觀, 也讓程式碼更加簡潔。 說明: java的泛型是停留在編譯層的, 也就是說JVM在對待泛型資料的時候, 依然會把它們看成是Object型別, 只不過在使用這些元素的時候, JVM會自動幫助我們進行相應的型別轉換。 總結: 集合使用泛型之後, 可以達到元素型別明確的目的, 避免了手動型別轉換的過程, 同時,也讓我們更加明確 容器儲存的是什麼型別的資料。
55.我們能否使用任何類作為Map的key?
1、可以 但是做為key的資料有如下要求: 2、首先, 要求明確一點Map集合儲存資料的 主要目的是為了查詢 而List集合是為了輸出 3、既然是查詢那麼就要涉及到物件比較 我們說了如果要進行物件比較 就必須覆寫Object類中的equals()、hasCode() 至少覆寫equals()方法 簡單理解: 自己定義的類如果要想實現物件比較 就必須至少覆寫equals()方法 4、或則這麼說只要是自己定義的類 要想將其作為key 就必須覆寫equals()方法 5、實際工作中 key的型別一定是String型 (95%通用) 其餘的5%是沒事找事的 6、按標準開發、你會感到事半功倍, 不要沒事給自己找事, 當然求知精神是值得肯定的。
56.Map介面提供了哪些不同的集合檢視?
Map介面提供了三個集合檢視: 1.Set keyset(): 返回map中包含的所有key的一個Set檢視。 集合是受map支援的, map的變化會在集合中反映出來, 反之亦然。 當一個迭代器正在遍歷一個集合時, 若map被修改了(除迭代器自身的移除操作以外), 迭代器的結果會變為未定義。 集合支援通過 Iterator的Remove、 Set.remove、 removeAll、 retainAll和clear操作進行元素移除, 從map中移除對應的對映。 它不支援add和addAll操作。 2.Collection values(): 返回一個map中包含的 所有value的一個Collection檢視。 這個collection受map支援的, map的變化會在collection中反映出來, 反之亦然。 當一個迭代器正在遍歷一個collection時, 若map被修改了(除迭代器自身的移除操作以外), 迭代器的結果會變為未定義。 集合支援通過 Iterator的Remove、 Set.remove、 removeAll、 retainAll和clear操作進行元素移除, 從map中移除對應的對映。 它不支援add和addAll操作。 3.Set> entrySet(): 返回一個map鍾包含的 所有對映的一個集合檢視。 這個集合受map支援的, map的變化會在collection中反映出來, 反之亦然。 當一個迭代器正在遍歷一個集合時, 若map被修改了 除迭代器自身的移除操作, 以及對迭代器返回的entry進行setValue外, 迭代器的結果會變為未定義。 集合支援通過 Iterator的Remove、 Set.remove、 removeAll、 retainAll和clear操作進行元素移除, 從map中移除對應的對映。 它不支援add和addAll操作。
57.哪些集合類是執行緒安全的?
在集合框架中,有些類是執行緒安全的, 這些都是jdk1.1中的出現的。 在jdk1.2之後, 就出現許許多多非執行緒安全的類。 下面是這些執行緒安全的同步的類: vector: 就比arraylist多了個同步化機制(執行緒安全), 因為效率較低, 現在已經不太建議使用。 在web應用中, 特別是前臺頁面, 往往效率(頁面響應速度)是優先考慮的。 statck:堆疊類,先進後出 hashtable:就比hashmap多了個執行緒安全 enumeration:列舉,相當於迭代器 除了這些之外, 其他的都是非執行緒安全的類和介面。 執行緒安全的類其方法是同步的, 每次只能一個訪問。 是重量級物件, 效率較低。
58.佇列和棧是什麼,列出它們的區別?
佇列(Queue): 是限定只能在表的一端進行 插入和在另一端進行刪除操作的線性表; 棧(Stack): 是限定只能在表的一端 進行插入和刪除操作的線性表。 區別如下: 一、規則不同 1. 佇列:先進先出(First In First Out)FIFO 2. 棧:先進後出(First In Last Out )FILO 二、對插入和刪除操作的限定不同 1. 佇列:只能在表的一端進行插入, 並在表的另一端進行刪除; 2. 棧:只能在表的一端插入和刪除。 三、遍歷資料速度不同 1. 佇列:基於地址指標進行遍歷, 而且可以從頭部或者尾部進行遍歷, 但不能同時遍歷, 無需開闢空間, 因為在遍歷的過程中不影響資料結構, 所以遍歷速度要快; 2. 棧:只能從頂部取資料, 也就是說最先進入棧底的, 需要遍歷整個棧才能取出來, 而且在遍歷資料的同時需要 為資料開闢臨時空間, 保持資料在遍歷前的一致性。
59.哪一個List實現了最快插入?
LinkedList和ArrayList 是另個不同變數列表的實現。 ArrayList的優勢在於動態的增長陣列, 非常適合初始時總長度未知的情況下使用。 LinkedList的優勢在於在中間位置插入和刪除操作, 速度是最快的。 LinkedList實現了List介面, 允許null元素。 此外LinkedList提供額外的 get,remove,insert方法 在LinkedList的首部或尾部。 這些操作使LinkedList可被 用作堆疊(stack), 佇列(queue) 或雙向佇列(deque)。 ArrayList實現了可變大小的陣列。 它允許所有元素, 包括null。 每個ArrayList例項都有一個容量(Capacity), 即用於儲存元素的陣列的大小。 這個容量可隨著不斷新增新元素而自動增加, 但是增長演算法並沒有定義。 當需要插入大量元素時, 在插入前可以呼叫ensureCapacity方法來 增加ArrayList的容量以提高插入效率。
60.什麼時候使用ConcurrentHashMap?
快速失敗的Java迭代器 可能會引發ConcurrentModifcationException 在底層集合迭代過程中被修改。 故障安全作為發生在例項中的一個副本 迭代是不會丟擲任何異常的。 快速失敗的故障安全範例定義了 當遭遇故障時系統是如何反應的。 例如,用於失敗的快速迭代器ArrayList 和用於故障安全的迭代器ConcurrentHashMap。 ConcurrentHashMap被作為 故障安全迭代器的一個例項, 它允許完整的併發檢索和更新。 當有大量的併發更新時, ConcurrentHashMap此時可以被使用。 這非常類似於Hashtable, 但ConcurrentHashMap不鎖定 整個表來提供併發, 所以從這點上ConcurrentHashMap的效能 似乎更好一些。 所以當有大量更新時 ConcurrentHashMap應該被使用。
61.什麼是併發修改異常?
什麼是併發修改異常: 當我們在遍歷實現了collection介面 與iterator介面的集合時(List、Set、Map), 我們可以通過遍歷索引 也可以通過迭代器進行遍歷。 在我們使用迭代器進行遍歷集合的時候, 會獲取到當前集合的迭代物件。 在裡面有封裝了迭代器的remove方法 與集合自帶的remove方法, 如果我們呼叫迭代器物件的remove方法 是沒問題的, 但是當我們呼叫集合自帶的remove方法時, 就會產生ConcurrentModificationException 併發修改異常。 也就是說, 當我們通過迭代器進行遍歷集合的時候, 是不允許集合本身在結構上發生變化的。
62.什麼是CopyOnWriteArrayList,它與ArrayList有何不同?
CopyOnWriteArrayList: CopyOnWriteArrayList這是一個 ArrayList的執行緒安全的變體, 其原理大概可以通俗的理解為: 初始化的時候只有一個容器, 很常一段時間, 這個容器資料、 數量等沒有發生變化的時候, 大家(多個執行緒),都是讀取 假設這段時間裡只發生讀取的操作 同一個容器中的資料, 所以這樣大家讀到的資料都是 唯一、一致、安全的, 但是後來有人往裡面增加了一個數據, 這個時候CopyOnWriteArrayList 底層實現 新增的原理是先copy出一個容器 可以簡稱副本, 再往新的容器裡新增這個新的資料, 最後把新的容器的引用地址 賦值給了之前那個舊的的容器地址, 但是在新增這個資料的期間, 其他執行緒如果要去讀取資料, 仍然是讀取到舊的容器裡的資料。 Vector ArrayList CopyOnWriteArrayList 這三個集合類都繼承List介面 1、ArrayList是執行緒不安全的; 2、Vector是比較古老的執行緒安全的, 但效能不行; 3、CopyOnWriteArrayList在兼顧了 執行緒安全的同時, 又提高了併發性, 效能比Vector有不少提高
63.迭代器和列舉之間的區別?
在Java集合中, 我們通常都通過 “Iterator(迭代器)” 或 “Enumeration(列舉類)” 去遍歷集合。 Enumeration是一個介面,它的原始碼如下: package java.util; public interface Enumeration<E> { boolean hasMoreElements() E nextElement(); } Iterator也是一個介面,它的原始碼如下: package java.util; public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } 區別: 1 函式介面不同 Enumeration只有2個函式介面。 通過Enumeration, 我們只能讀取集合的資料, 而不能對資料進行修改。 Iterator只有3個函式介面。 Iterator除了能讀取集合的資料之外, 也能資料進行刪除操作。 2.Iterator支援fail-fast機制,而Enumeration不支援。 Enumeration 是JDK 1.0新增的介面。 使用到它的函式包括Vector、Hashtable等類, 這些類都是JDK 1.0中加入的, Enumeration存在的目的 就是為它們提供遍歷介面。 Enumeration本身並沒有支援同步, 而在Vector、Hashtable實現Enumeration時, 添加了同步。 而Iterator 是JDK 1.2才新增的介面, 它也是為了HashMap、ArrayList等集合 提供遍歷介面。 Iterator是支援fail-fast機制的: 當多個執行緒對同一個集合的內容進行操作時, 就可能會產生fail-fast事件。 Java API規範建議, 對於較新的程式, Iterator應優先於Enumeration, 因為“ Iterator在Java集合框架中 代替Enumeration。”
64.Hashmap如何同步?
1、使用 synchronized 關鍵字, 這也是最原始的方法。 synchronized(anObject) { value = map.get(key); } 2、使用 JDK1.5 提供的鎖 Java.util.concurrent.locks.Lock lock.lock(); value = map.get(key); lock.unlock(); 3.可以使用 JDK1.5 提供的讀寫鎖 java.util.concurrent.locks.ReadWriteLock rwlock.readLock().lock(); value = map.get(key); rwlock.readLock().unlock(); 4.使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 類 該類將 Map 的儲存空間分為若干塊, 每塊擁有自己的鎖, 大大減少了多個執行緒 爭奪同一個鎖的情況 value = map.get(key); 1、不同步確實最快,與預期一致。 2、四種同步方式中, ConcurrentHashMap 是最快的, 接近不同步的情況。 3、synchronized 關鍵字非常慢 4、使用讀寫鎖的讀鎖,比普通所稍慢。 1、如果 ConcurrentHashMap 夠用, 則使用 ConcurrentHashMap。 2、如果需自己實現同步, 則使用 JDK1.5 提供的鎖機制, 避免使用 synchronized 關鍵字。
65.IdentityHashMap和HashMap的區別?
前者比較key時是 “引用相等” 而後者是 “物件相等”, 即對於 k1和k2,當k1==k2時, IdentityHashMap認為兩個key相等, 而HashMap只有在k1.equals(k2) == true 時 才會認為兩個key相等。 2.IdentityHashMap 允許使用null作為key和value. 不保證任何Key-value對的之間的順序, 更不能保證他們的順序 隨時間的推移不會發生變化。 3.IdentityHashMap有其特殊用途, 比如序列化或者深度複製。或 者記錄物件代理。 舉個例子, jvm中的所有物件都是獨一無二的, 哪怕兩個物件是同一個class的物件 而且兩個物件的資料完全相同, 對於jvm來說, 他們也是完全不同的, 如果要用一個map來記錄這樣jvm中的物件, 你就需要用IdentityHashMap, 而不能使用其他Map實現
66.如何獲取某個日期是當月的最後一天?
import java.util.Calendar; public class Test { public static void main(String[] args) { System.out.println(daysCount(2010, 2)); } public static int daysCount(int year, int month) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, month); cal.set(Calendar.DATE, 0); return cal.get(Calendar.DATE); } }
67.java中會存在記憶體洩漏嗎,請簡單描述
所謂記憶體洩露就是指 一個不再被程式使用的物件或變數 一直被佔據在記憶體中。 Java中有垃圾回收機制, 它可以保證一物件不再被引用的時候, 即物件程式設計了孤兒的時候, 物件將自動被垃圾回收器 從記憶體中清除掉。 由於Java 使用有向圖的方式 進行垃圾回收管理, 可以消除引用迴圈的問題, 例如有兩個物件,相互引用, 只要它們和根程序不可達的, 那麼GC也是可以回收它們的。 java中的記憶體洩露的情況: 長生命週期的物件持有 短生命週期物件的引用 就很可能發生記憶體洩露, 儘管短生命週期物件已經不再需要, 但是因為長生命週期物件 持有它的引用而導致不能被回收, 這就是java中記憶體洩露的發生場景, 通俗地說, 就是程式設計師可能建立了一個物件, 以後一直不再使用這個物件, 這個物件卻一直被引用, 即這個物件無用 但是卻無法被垃圾回收器回收的, 這就是java中可能出現 記憶體洩露的情況, 例如,快取系統, 我們載入了一個物件放在快取中(例如放在一個全域性map物件中), 然後一直不再使用它, 這個物件一直被快取引用, 但卻不再被使用。 檢查java中的記憶體洩露, 一定要讓程式將各種分支情況 都完整執行到程式結束, 然後看某個物件是否被使用過, 如果沒有, 則才能判定這個物件屬於記憶體洩露。 如果一個外部類的例項物件的方法 返回了一個內部類的例項物件, 這個內部類物件被長期引用了, 即使那個外部類例項物件不再被使用, 但由於內部類持久外部類的例項物件, 這個外部類物件將不會被垃圾回收, 這也會造成記憶體洩露。 記憶體洩露的另外一種情況: 當一個物件被儲存進HashSet集合中以後, 就不能修改這個物件中的 那些參與計算雜湊值的欄位了, 否則,物件修改後的雜湊值 與最初儲存進HashSet集合中時的雜湊值 就不同了, 在這種情況下, 即使在contains方法使用該物件的 當前引用作為的引數去HashSet集合中 檢索物件, 也將返回找不到物件的結果, 這也會導致無法從HashSet集合中 單獨刪除當前物件, 造成記憶體洩露
68.java中實現多型的機制是什麼?
靠的是父類或介面的 引用指向子類或實現類的物件, 呼叫的方法是記憶體中 正在執行的那個物件的方法。 Java實現多型有三個必要條件: 繼承、 重寫、 向上轉型。 繼承: 在多型中必須存在 有繼承關係的子類和父類。 重寫: 子類對父類中某些方法進行重新定義, 在呼叫這些方法時 就會呼叫子類的方法。 向上轉型: 在多型中需要將子類的引用 賦給父類物件, 只有這樣該引用才能夠具備 技能呼叫父類的方法和子類的方法。 只有滿足了上述三個條件, 我們才能夠在同一個繼承結構中 使用統一的邏輯實現程式碼處理不同的物件, 從而達到執行不同的行為。 多型機制遵循的原則概括為 當超類物件引用變數引用子類物件時, 被引用物件的型別 而不是引用變數的型別 決定了呼叫誰的成員方法, 但是這個被呼叫的方法 必須是在超類中定義過的, 也就是說被子類覆蓋的方法, 但是它仍然要根據繼承鏈中 方法呼叫的優先順序來確認方法, 該優先順序為: this.method(O)、 super.method(O)、 this.method((super)O)、 super.method((super)O)。
69.區域性變數和成員變數的區別?
成員變數與區域性變數的區別 1、在類中的位置不同 成員變數: 在類中方法外面 區域性變數: 在方法或者程式碼塊中, 或者方法的宣告上 2、在記憶體中的位置不同, 成員變數:在堆中(方法區中的靜態區) 區域性變數:在棧中 3、生命週期不同 成員變數: 隨著物件的建立而存在, 隨著物件的消失而消失 區域性變數: 隨著方法的呼叫或者程式碼塊的執行 而存在, 隨著方法的呼叫完畢或者 程式碼塊的執行完畢而消失 4、初始值 成員變數: 有預設初始值 區域性變數: 沒有預設初始值, 使用之前需要賦值, 否則編譯器會報錯
70.什麼是匿名類,有什麼好處?
簡單地說: 匿名內部類就是沒有名字的內部類。 什麼情況下需要使用匿名內部類? 如果滿足下面的一些條件, 使用匿名內部類是比較合適的: 只用到類的一個例項。 類在定義後馬上用到。 類非常小(SUN推薦是在4行程式碼以下) 給類命名並不會導致你的程式碼更容易被理解。 在使用匿名內部類時,要記住以下幾個原則: 匿名內部類不能有構造方法。 匿名內部類不能定義任何靜態成員、方法和類。 匿名內部類不能是 public,protected,private,static。 只能建立匿名內部類的一個例項。 一個匿名內部類一定是在new的後面, 用其隱含實現一個介面或實現一個類。 因匿名內部類為區域性內部類, 所以區域性內部類的所有限制都對其生效。
71.jsp有哪些內建物件?作用分別是什麼?
Page, pageContext, request, response, session, application, out, config, exception Page指的是JSP被翻譯成Servlet的物件的引用. pageContext物件可以用來獲得其他8個內建物件, 還可以作為JSP的域範圍物件使用. pageContext中存的值是當前的頁面的作用範圍 request代表的是請求物件, 可以用於獲得客戶機的資訊, 也可以作為域物件來使用, 使用request儲存的資料 在一次請求範圍內有效。 Session代表的是一次會話, 可以用於儲存使用者的私有的資訊, 也可以作為域物件使用, 使用session儲存的資料在一次會話範圍有效 Application:代表整個應用範圍, 使用這個物件儲存的資料 在整個web應用中都有效。 Response是響應物件, 代表的是從伺服器向瀏覽器響應資料. Out:JSPWriter是用於 向頁面輸出內容的物件 Config:指的是ServletConfig 用於JSP翻譯成Servlet後 獲得Servlet的配置的物件. Exception:在頁面中設定isErrorPage=”true”, 即可使用, 是Throwable的引用.用來獲得頁面的錯誤資訊。
72.jsp有哪些動作?作用分別是什麼?
jsp:include: 在頁面被請求的時候引入一個檔案。 jsp:useBean: 尋找或者例項化一個JavaBean。 jsp:setProperty: 設定JavaBean的屬性。 jsp:getProperty: 輸出某個JavaBean的屬性。 jsp:plugin: 根據瀏覽器型別為Java外掛生成OBJECT或EMBED標記。 jsp:forward: 把請求轉到一個新的頁面。
73.JSP中動態INCLUDE與靜態INCLUDE的區別?
1. 靜態include的結果是 把其他jsp引入當前jsp, 兩者合為一體 動態include的結構是兩者獨立, 直到輸出時才合併 看看jsp生成的java檔案就可以知道了 2.正是因為這樣, 動態include的jsp檔案獨立性很強, 是一個單獨的jsp檔案, 需要使用的物件, 頁面設定,都必須有自己建立, 當然,還好它和include 它的頁面的request範圍是一致的. 而靜態include純粹是把程式碼 寫在外面的一種共享方法, 所有的變數都是可以 和include它的主檔案共享 ,兩者高度緊密結合, 不能有變數同名的衝突. 而頁面設定也可以借用主檔案的.
74.說一說Servlet的生命週期?
servlet 的生命週期是有四個階段: 例項化 –> 初始化 –> 請求處理 –> 銷燬 建立 Servlet 例項。 Web 容器呼叫 Servlet 的 init() 方法, 對Servlet 進行初始化。 Servlet 初始化後, 將一直存在於容器中, 用於響應客戶端請求。 根據客戶端的請求方式通過 Servlet 中service() 方法 去相應的 goGet(),或 doPost() 方法; Web 容器銷燬Servlet 時, 呼叫 Servlet 的 destroy() 方法, 通常在關閉Web容器之時銷燬Servlet。 servlet 生命週期的三個方法: init()方法: Servlet例項化時呼叫此方法 Service()方法: 客戶請求和響應呼叫此方法。 Destroy()方法: 釋放記憶體,關閉web伺服器呼叫此方法
75.說說JSP 的生命週期?
瀏覽器首先要請求一個以.jsp副檔名結尾的頁面, 發起JSP請求, 然後,Web伺服器讀取這個請求, 使用JSP編譯器把JSP頁面 轉化成一個Servlet類。 需要注意的是, 只有當第一次請求頁面 或者是JSP檔案發生改變的時候 JSP檔案才會被編譯, 然後伺服器呼叫servlet類, 處理瀏覽器的請求。 一旦請求執行結束, servlet會把響應傳送給客戶端。 jsp 的生命週期分為四個階段: 編譯 初始化 執行 銷燬
76、XML技術的作用?
XML技術用於資料儲存、 資訊配置、 資料交換三方面。 可以將資料儲存在XML中, 通過節點、 元素內容、 屬性標示資料內容及關係。 可以使用XML很方便的做資訊配置, 軟體的各種配置引數和物件關係 都存貯在XML檔案中。 在做資料交換平臺時, 將資料組裝成XML檔案, 然後將XML檔案壓縮打包加密後 通過網路傳送給接收者, 接收解密與解壓縮後再同XML檔案中 還原相關資訊進行處理。
77.XML文件約束有哪幾種?有什麼區別?
有兩種定義形式, dtd文件型別定義和SchemaXML模式; XML Schema 和DTD都用於文件驗證, 但二者還有一定的區別, 本質區別是:Scheme本身是xml的, 可以被XML解析器解析, 這也是從DTD上發展Schema的根本目的。 另外, XML Schema 是內容開放模型, 可擴充套件,功能性強, 而DTD可擴充套件性差。 XML Schema 支援豐富的資料型別, 而 DTD不支援元素的資料型別, 對屬性的型別定義也很有限。 XML Schema 支援名稱空間機制, 而DTD不支援。 XML Schema 可針對不同情況 對整個XML 文件或文件區域性進行驗證; 而 DTD缺乏這種靈活性。 XML Schema 完全遵循XML規範, 符合XML語法, 可以和DOM結合使用, 功能強大; 而DTD 語法本身有自身的語法和要求, 難以學習。
78.XML的解析方式有哪幾種?有什麼區別?
1.DOM解析: DOM的全稱是Document Object Model, 也即文件物件模型。 在應用程式中, 基於DOM的XML分析器 將一個XML文件轉換成 一個物件模型的集合(通常稱DOM樹), 應用程式正是通過對 這個物件模型的操作, 來實現對XML文件資料的操作。 通過DOM介面, 應用程式可以在任何時候 訪問XML文件中的任何一部分資料, 因此,這種利用DOM介面的機制 也被稱作隨機訪問機制。 2.SAX解析: SAX的全稱是Simple APIs for XML, 也即XML簡單應用程式介面。 與DOM不同, SAX提供的訪問模式是一種順序模式, 這是一種快速讀寫XML資料的方式。 當使用SAX分析器對XML文件進行分析時, 會觸發一系列事件, 並激活相應的事件處理函式, 應用程式通過這些事件處理函式 實現對XML文件的訪問, 因而SAX介面也被稱作事件驅動介面。 3.JDOM解析: JDOM採用了Java中的Collection架構來封裝集合, 是Java愛好者更加熟悉的模式 4.DOM4J解析: xml解析器一次性把整個xml文件載入進記憶體, 然後在記憶體中構建一顆Document的物件樹, 通過Document物件, 得到樹上的節點物件, 通過節點物件訪問(操作)到xml文件的內容
79.Http請求的Get和Post的區別?
1. get從位址列以明文的方式提交請求 資訊內容 ?username=admin&password=123, 使用者可見, 而post從請求正文提交請求資訊內容, 使用者不可見。 2. get提交因為是從位址列傳遞, 而瀏覽器的位址列長度有限制, 不能提交大資料 post從請求正文傳遞資訊內容, 對檔案大小無限制, 檔案上傳只能選擇post 3. request物件是伺服器獲取請求資訊 從請求頭,請求正文中獲取 我們可以使用request.setCharacterEncoding方法 修改請求物件字元編碼資訊, 但是不能修改位址列字元編碼。 get從位址列傳遞資訊, 不能使用request.setCharacterEncoding這個方法 去修改字元編碼。 post從請求正文以form表單形式提交, 所以可以使用request.setCharacterEncoding 這個方法去修改字元編碼。 4. 總結: 能夠使用post提交儘量使用post提交。
80.ServletConfig物件和ServletContext物件有什麼區別?
一個Servlet對應有一個ServletConfig物件, 可以用來讀取初始化引數。 一個webapp對應一個ServletContext物件。 ServletContext物件 獲取初始化定義的引數。 ServletContext物件可以通過 context.getResourceAsStream("/PATH"); 或者context.getRealPath("/")。 去獲取webapp的資原始檔。 ServletContext物件的 setAttribute(String name,Object o)方法 可以將物件儲存在Context作用範圍域 又稱為全域性作用範圍域, 在整個web應用當中可以共享. ServletContext物件 可以和伺服器進行通訊, 比如寫資訊到伺服器的日誌資訊當中。。
81.Servlet的會話機制?
HTTP 是一種無狀態協議, 這意味著每次客戶端檢索網頁時, 都要單獨開啟一個伺服器連線, 因此伺服器不會記錄下 先前客戶端請求的任何資訊。 它與FTP、Telnet等協議不同, FTP等協議可以記住使用者的連線資訊。 會話(Session)是指一個終端使用者 與互動系統進行通訊的時間間隔, 通常指從登陸系統到登出系統之間 所經過的時間以及如果需要的話, 可能還有一定操作空間。 JSP有四種方式實現會話跟蹤功能。 Cookie 伺服器在響應請求時 可以將一些資料以"鍵-值"對的形式 通過響應資訊儲存在客戶端。 當瀏覽器再次訪問相同的應用時, 會將原先的存有session ID的Cookie 通過請求資訊帶到伺服器端, 網路伺服器通過識別唯一的session ID來 代表每個客戶端, 從而識別這個客戶端接下來的請求。 用於會話跟蹤的Cookie叫做會話Cookie。 Servlet規範中會話跟蹤的cookie名字 必須是JSESSIONID, 儲存在瀏覽器的記憶體中。 Cookie可以用於保持使用者的會話狀態, 但Cookie資訊儲存在客戶端, 存在較大的安全隱患, 且一般瀏覽器對Cookie的數目 及資料大小有嚴格的限制。 在Web應用中, 一般情況下通過HttpSession物件保持會話狀態 Session Session技術則是 服務端的解決方案, 它是通過伺服器來保持狀態的。 在Java中是通過呼叫 HttpServletRequest的getSession方法 使用true作為引數建立的。 在建立了Session的同時, 伺服器會為該Session生成唯一的Session id, 而這個Session id在隨後的請求中 會被用來重新獲得已經建立的Session; 在Session被建立之後, 就可以呼叫Session相關的方法 往Session中增加內容了, 而這些內容只會儲存在伺服器中, 發到客戶端的只有Session id; 當客戶端再次傳送請求的時候, 會將這個Session id帶上, 伺服器接受到請求之後 就會依據Session id找到相應的Session, 從而再次使用之。 正式這樣一個過程, 使用者的狀態也就得以保持了。 隱藏表單域 隱藏表單域是將會話ID 新增到HTML的隱藏表單中 (型別為hidden的input)。 重定向和轉發 重寫URL 把會話ID編碼在URL中。 counter.jsp;jsessionnid=be8d697876787876befdbde898789098980 對於URL複寫, 伺服器從請求的URI中提取出會話ID, 並把該請求與相應的會話關聯起來, 然後在訪問會話資料的時候, JSP頁面所進行的處理方式 就和使用cookie跟蹤會話id時 所使用的方式完全相同。 所以sesssion的實現 要依靠cookie或URL複寫技術。
82.Filter是什麼?有什麼作用?
過濾器是處於客戶端與伺服器 資原始檔之間的一道過濾網, 在訪問資原始檔之前, 通過一系列的過濾器對請求進行修改、判斷等, 把不符合規則的請求在中途攔截或修改。 也可以對響應進行過濾, 攔截或修改響應。

瀏覽器發出的請求先遞交給第一個filter進行過濾, 符合規則則放行, 遞交給filter鏈中的下一個過濾器進行過濾。 過濾器在鏈中的順序 與它在web.xml中配置的順序有關, 配置在前的則位於鏈的前端。 當請求通過了鏈中所有過濾器後 就可以訪問資原始檔了, 如果不能通過, 則可能在中間某個過濾器中被處理掉。 在doFilter()方法中, chain.doFilter()前的一般是對request執行的過濾操作, chain.doFilter後面的程式碼 一般是對response執行的操作。 過濾器一般用於登入許可權驗證、 資源訪問許可權控制、 敏感詞彙過濾、 字元編碼轉換等等操作, 便於程式碼重用, 不必每個servlet中還要進行相應的操作。
83.Listener是什麼?有什麼作用?
監聽器用於監聽web應用中某些物件、 資訊的建立、銷燬、增加,修改,刪除等 動作的發生, 然後作出相應的響應處理。 當範圍物件的狀態發生變化的時候, 伺服器自動呼叫監聽器物件中的方法。 常用於統計線上人數和線上使用者, 系統載入時進行資訊初始化, 統計網站的訪問量等等。 分類: 按監聽的物件劃分,可以分為 ServletContext物件監聽器 HttpSession物件監聽器 ServletRequest物件監聽器 按監聽的事件劃分 物件自身的建立和銷燬的監聽器 物件中屬性的建立和消除的監聽器 session中的某個物件的狀態變化的監聽器
84.你瞭解過Servlet3.0嗎?
Servlet3.0相對於Servlet2.0來說 最大的改變是引入了Annotation註解 來取代xml配置, 用於簡化web應用的開發和部署。 最主要幾項特性: 1. 新增的註解支援: 該版本新增了若干註解, 用於簡化 Servlet、 過濾器(Filter) 和監聽器(Listener)的宣告, 這使得 web.xml 部署描述檔案 從該版本開始不再是必選的了。 2. 非同步處理支援: 有了該特性, Servlet 執行緒不再需要一直阻塞, 直到業務處理完畢才能再輸出響應, 最後才結束該 Servlet 執行緒。 在接收到請求之後, Servlet 執行緒可以將耗時的操作 委派給另一個執行緒來完成, 自己在不生成響應的情況下返回至容器。 針對業務處理較耗時的情況, 這將大大減少伺服器資源的佔用, 並且提高 併發處理速度。 3. 可插性支援: 熟悉 Struts2 的開發者一定會 對其通過外掛的方式 與包括 Spring 在內的各種常用框架的整合 特性記憶猶新。 將相應的外掛封裝成 JAR 包並放在類路徑下, Struts2 執行時便能自動載入這些外掛。 現在 Servlet 3.0 提供了類似的特性, 開發者可以通過外掛的方式很方便的 擴充已有 Web 應用的功能, 而不需要修改原有的應用。
85.JSP和Servlet有哪些相同點和不同點?
JSP是Servlet技術的擴充套件, 本質上是Servlet的簡易方式, 更強調應用的外表表達。 JSP編譯後是"類servlet"。 Servlet和JSP最主要的不同點在於, Servlet的應用邏輯是在Java檔案中, 並且完全從表示層中的HTML裡分離開來。 而JSP的情況是 Java和HTML可以組合 成一個副檔名為.jsp的檔案。 在實際專案開發當中, JSP側重於檢視, Servlet主要用於控制邏輯。
86.如何獲得高效的資料庫邏輯結構?
從關係資料庫的表中 刪除冗餘資訊的過程 稱為資料規範化, 是得到高效的關係型資料庫表的邏輯結構 最好和最容易的方法。 規範化資料時應執行以下操作: 1.將資料庫的結構精簡為最簡單的形式 2.從表中刪除冗餘值 3.標識所有依賴與其他資料的資料 規範化過程有幾個階段, 分別稱作第一正規化(1NF)、 第二正規化(2NF)、 第三正規化(3NF)、 第四正規化(4NF) 以及第五正規化(5NF)。 對於所有的實際應用, 3NF已經足夠了。
87.資料庫三正規化是什麼?
第一正規化(1NF): 欄位具有原子性,不可再分。 所有關係型資料庫系統 都滿足第一正規化) 資料庫表中的欄位都是單一屬性的, 不可再分。 例如,姓名欄位, 其中的姓和名必須作為一個整體, 無法區分哪部分是姓, 哪部分是名, 如果要區分出姓和名, 必須設計成兩個獨立的欄位。 第二正規化(2NF): 第二正規化(2NF)是在第一正規化(1NF)的基礎上 建立起來的,即滿足第二正規化(2NF) 必須先滿足第一正規化(1NF)。 要求資料庫表中的每個例項 或行必須可以被惟一地區分。 通常需要為表加上一個列, 以儲存各個例項的惟一標識。 這個惟一屬性列被 稱為主關鍵字或主鍵。 第二正規化(2NF)要求實體的屬性 完全依賴於主關鍵字。 所謂完全依賴是指不能存在 僅依賴主關鍵字一部分的屬性, 如果存在, 那麼這個屬性和主關鍵字的這一部分 應該分離出來形成一個新的實體, 新實體與原實體之間是一對多的關係。 為實現區分通常需要為表加上一個列, 以儲存各個例項的惟一標識。 簡而言之, 第二正規化就是非主屬性 非部分依賴於主關鍵字。 第三正規化(3NF) 是在第二正規化的基礎上建立起來的, 即滿足第三正規化(3NF) 必須先滿足第二正規化(2NF)。 第三正規化(3NF)要求 非主關鍵字不能依賴於 其他非主關鍵字。 即非主關鍵字之間 不能有函式(傳遞)依賴關係. 即不能從一個表的某個欄位 推出該表的另一個欄位。 滿足三正規化的設計, 基本可以解決資料冗餘、 插入異常、 更新異常、 刪除異常等資料儲存問題。
88.SQL語句分為哪幾種?
SQL語句主要可以劃分為以下幾類: DDL(Data Definition Language): 資料定義語言, 定義對資料庫物件(庫、表、列、索引)的操作。 包括: CREATE、 DROP、 ALTER、 RENAME、 TRUNCATE等 DML(Data Manipulation Language): 資料操作語言, 定義對資料庫記錄的操作。 包括: INSERT、 DELETE、 UPDATE、 SELECT等 DCL(Data Control Language): 資料控制語言, 定義對資料庫、表、欄位、 使用者的訪問許可權和安全級別。 包括: GRANT、 REVOKE等 Transaction Control: 事務控制 包括: COMMIT、 ROLLBACK、 SAVEPOINT等
89. Delete、truncaate、drop都是刪除語句,它們有什麼分別?
delete 屬於DML語句, 刪除資料, 保留表結構, 需要commit, 可以回滾, 如果資料量大, 很慢。 truncate 屬於DDL語句, 刪除所有資料, 保留表結構, 自動commit, 不可以回滾, 一次全部刪除所有資料, 速度相對較快。 Drop屬於 DDL語句, 刪除資料和表結構, 不需要commit, 刪除速度最快。
90.Where和having都是條件篩選關鍵字,它們有什麼分別?
1.Where語句是一條一條從磁碟讀取的, 然後進行判斷, 滿足條件的存放到記憶體, 不滿足忽略, 而having是將所有的資料讀入記憶體中, 然後在記憶體內部逐條判斷, 不滿足直接刪除 where是判斷資料從磁碟 讀入記憶體的時候, having是判斷分組 統計之前的所有條件 2.having子句中可以使用欄位別名, 而where不能使用 3.having能夠使用統計函式, 但是where不能使用 4.where 後不能跟聚合函式, 因為where執行順序大於聚合函式。 5.having 是篩選組 而where是篩選記錄 注意:HAVING用於應被用於WHERE子句的條目, 從我們開頭的2條語句來看, 這樣用並沒有出錯, 但是mysql不推薦。 而且也沒有明確說明原因, 但是既然它要求, 我們遵循就可以了
91.如何提升資料查詢的效率?
1.首先檢查表的結構是否合理, 因為採用多表查詢的時候, 看主外來鍵的引用關係是否適當. 如果不適當則重新設定表結構. 如果是應用中的系統, 則不需要更改表的欄位, 只更改主外來鍵關係. 如果資料庫中有較多的資料, 還應採用索引提高查詢效率. 2.利用索引(index) 對查詢進行優化, index可以避免對錶資料的全面掃描, 當你以某個欄位建立一個索引的時候, 資料庫就會生成一個索引頁, 索引頁不單單儲存索引的資料, 還儲存了索引在資料庫的 具體的實體地址, 能夠很快的定位查詢到要找的記錄 3. 如果表的列很少, 不適合建索引. 表資料很少查詢, 而經常做insert、delete、update動作, 不適合建所以。 因為Oracle需要對索引額外維護。 建立索引後,select會快, 當執行過多次的insert,delete,update後, 會出現索引碎片, 影響查詢速度,我 們應該對索引進行重組 (即drop掉索引重新create) 4.索引的型別分為: B-樹索引: 適合於大量的增、刪、改, 大多數資料的索引預設型別。 點陣圖索引: 適合於決策支援系統 HASH索引、分割槽索引等。
92.什麼是資料庫事務?
事務是作為一個邏輯單元 執行的一系列操作, 要麼一起成功,要麼一起失敗。 一個邏輯工作單元必須有四個屬性, 稱為 ACID: 原子性、 一致性、 隔離性 永續性 屬性, 只有這樣才能成為一個事務。 原子性 : 事務必須是原子工作單元; 對於其資料修改, 要麼全都執行 ,要麼全都不執行。 一致性 : 事務在完成時, 必須使所有的資料都保持一致狀態。 在相關資料庫中, 所有規則都必須應用於事務的修改, 保持所有資料的完整性。 事務結束時, 所有的內部資料結構 (如 B 樹索引或雙向連結串列) 都必須是正確的。 隔離性 : 由併發事務所作的修改 必須與任何其它併發事務 所作的修改隔離。 事務檢視資料時資料所處的狀態, 要麼另一併發事務修改它之前的狀態, 要麼是另一事務修改它之後的狀態, 事務不會檢視中間狀態的資料。 這為可序列性, 因為它能夠重新裝載起始資料, 並且重播一系列事務, 以使資料結束時的狀態 與原始事務執的狀態相同。 永續性 : 事務完成之後, 它對於系統的影響是永久性的。 該修改即使出現系統故障也將一直保持。
93.什麼是資料庫事務的隔離級別?
多個執行緒開啟各自事務操作資料庫中資料時,數 據庫系統要負責隔離操作, 以保證各個執行緒在獲取資料時的準確性。 資料庫共定義了四種隔離級別: Serializable:(序列化) 可避免髒讀、 不可重複讀、 虛讀情況的發生 Repeatable read:(可重複讀) 可避免髒讀、 不可重複讀情況的發生。 Read committed:(讀已提交) 可避免髒讀情況發生。 Read uncommitted:(讀未提交) 最低級別, 以上情況均無法保證。
94.如何刪除表中的重複資料,只保留一條記錄?
1、查詢表中多餘的重複記錄, 重複記錄是根據單個欄位(peopleId)來判斷 select * from people where peopleId in ( select peopleId from people group by peopleId having count(peopleId) > 1 ) 2、刪除表中多餘的重複記錄, 重複記錄是根據單個欄位(peopleId)來判斷, 只留有rowid最小的記錄 delete from people wherepeopleName in ( select peopleNamefrom people group by peopleName having count(peopleName) > 1 ) andpeopleId not in ( select min(peopleId) from people group by peopleName having count(peopleName)>1 ) 3、查詢表中多餘的重複記錄(多個欄位) select * from vitae a where (a.peopleId,a.seq) in ( select peopleId,seq from vitae group by peopleId,seq having count(*) > 1 ) 4、刪除表中多餘的重複記錄(多個欄位),只留有rowid最小的記錄 delete from vitae a where (a.peopleId,a.seq) in ( select peopleId,seq from vitae group by peopleId,seq having count(*) > 1 ) and rowid not in ( select min(rowid) from vitae group by peopleId,seq having count(*)>1 ) 5、查詢表中多餘的重複記錄(多個欄位),不包含rowid最小的記錄 select * from vitae a where (a.peopleId,a.seq) in ( select peopleId,seq from vitae group by peopleId, seq having count(*) > 1 ) and rowid not in ( select min(rowid) from vitae group by peopleId, seq having count(*)>1 ) 6.消除一個欄位的左邊的第一位: update tableName set [Title]=Right([Title],(len([Title])-1)) where Title like '村%' 7.消除一個欄位的右邊的第一位: update tableName set [Title]=left([Title],(len([Title])-1)) where Title like '%村' 8.假刪除表中多餘的重複記錄(多個欄位), 不包含rowid最小的記錄 update vitae set ispass=-1 where peopleId in ( select peopleId from vitae group by peopleId )
95.如何通過sql語句完成分頁?
客戶端通過傳遞start(頁碼), PageSize(每頁顯示的條數)兩個引數 去分頁查詢資料庫表中的資料, 那我們知道MySql資料庫提供了 分頁的函式limit m,n, 但是該函式的用法和我們的需求不一樣, 所以就需要我們根據實際情況 去改寫適合我們自己的分頁語句, 具體的分析如下: 比如: 查詢第1條到第10條的資料的sql是: select * from table limit 0,10; 對應我們的需求就是查詢第一頁的資料: select * from table limit (1-1)*10,10; 查詢第10條到第20條的資料的sql是: select * from table limit 10,20; 對應我們的需求就是查詢第二頁的資料: select * from table limit (2-1)*10,10; 查詢第20條到第30條的資料的sql是: select * from table limit 20,30; 對應我們的需求就是查詢第三頁的資料: select * from table limit (3-1)*10,10; 二:通過上面的分析, 可以得出符合我們自己需求的分頁 sql格式是: select * from table limit (start-1)*PageSize,PageSize; 其中start是頁碼, PageSize是每頁顯示的條數。
ofollow,noindex">撩課Java+系統架構點選開始學習
96.JDBC操作資料庫的步驟 ?
1、載入資料庫驅動 2、建立並獲取資料庫連結 3、建立jdbc statement物件 4、設定sql語句 5、設定sql語句中的引數(使用preparedStatement) 6、通過statement執行sql並獲取結果 7、對sql執行結果進行解析處理 8、釋放資源(resultSet、preparedstatement、connection)
97.JDBC中的Statement 和PreparedStatement的區別?
Java提供了 Statement、 PreparedStatement CallableStatement 三種方式來執行查詢語句, 其中 Statement 用於通用查詢, PreparedStatement 用於執行引數化查詢, 而 CallableStatement則是用於儲存過程。 關於PreparedStatement介面, 需要重點記住的是: 1. PreparedStatement可以寫引數化查詢, 比Statement能獲得更好的效能。 2. 對於PreparedStatement來說, 資料庫可以使用已經編譯過 及定義好的執行計劃, 這種預處理語句查詢 比普通的查詢執行速度更快。 3. PreparedStatement可以阻止常見的 SQL注入式攻擊。 4. PreparedStatement可以寫動態查詢語句 5. PreparedStatement與 java.sql.Connection物件是關聯的, 一旦你關閉了connection, PreparedStatement也沒法使用了。 6. “?” 叫做佔位符。 7. PreparedStatement查詢 預設返回FORWARD_ONLY的ResultSet, 你只能往一個方向移動結果集的遊標。 當然你還可以設定為其他型別的 值如:”CONCUR_READ_ONLY”。 8. 不支援預編譯SQL查詢的JDBC驅動, 在呼叫connection.prepareStatement(sql)的時候, 它不會把SQL查詢語句傳送給資料庫做預處理, 而是等到執行查詢動作的時候 呼叫executeQuery()方法時 才把查詢語句傳送個數據庫, 這種情況和使用Statement是一樣的。 9. 佔位符的索引位置從1開始而不是0, 如果填入0會導致 java.sql.SQLException invalid column index異常。 所以如果PreparedStatement有兩個佔位符, 那麼第一個引數的索引時1, 第二個引數的索引是2.
98.說說資料庫連線池工作原理和實現方案?
一般來說,Java應用程式訪問資料庫的過程是: 1.裝載資料庫驅動程式; 2.通過jdbc建立資料庫連線; 3.訪問資料庫,執行sql語句; 4.斷開資料庫連線。 程式開發過程中,存在很多問題: 首先, 每一次web請求都要建立一次資料庫連線。 建立連線是一個費時的活動, 每次都得花費0.05s~1s的時間, 而且系統還要分配記憶體資源。 這個時間對於一次或幾次資料庫操作, 或許感覺不出系統有多大的開銷。 可是對於現在的web應用, 尤其是大型電子商務網站, 同時有幾百人甚至幾千人線上是很正常的事。 在這種情況下, 頻繁的進行資料庫連線操作 勢必佔用很多的系統資源, 網站的響應速度必定下降, 嚴重的甚至會造成伺服器的崩潰。 其次,對於每一次資料庫連線, 使用完後都得斷開。 否則,如果程式出現異常而未能關閉, 將會導致資料庫系統中的記憶體洩漏, 最終將不得不重啟資料庫 “資料庫連線”是一種稀缺的資源, 為了保障網站的正常使用, 應該對其進行妥善管理。 其實我們查詢完資料庫後, 如果不關閉連線, 而是暫時存放起來, 當別人使用時, 把這個連線給他們使用。 就避免了一次建立資料庫 連線和斷開的操作時間消耗。 資料庫連線池的基本思想: 就是為資料庫連線建立一個“緩衝池”。 預先在緩衝池中放入一定數量的連線, 當需要建立資料庫連線時, 只需從“緩衝池”中取出一個, 使用完畢之後再放回去。 我們可以通過設定連線池最大連線數 來防止系統無盡的與資料庫連線
99.execute,executeQuery,executeUpdate的區別是什麼?
在jdbc中有3種執行sql的語句分別是 execute, executeQuery executeUpdate ResultSetexecuteQuery(String sql); 執行SQL查詢,並返回ResultSet 物件。 方法executeQuery 用於產生單個結果集(ResultSet)的語句, 例如 SELECT 語句。 被使用最多的執行 SQL 語句的方法。 這個方法被用來執行 SELECT 語句, 它幾乎是使用最多的 SQL 語句。 但也只能執行查詢語句, 執行後返回代表查詢結果的ResultSet物件。 2.int executeUpdate(String sql); 可執行增,刪,改, 返回執行受到影響的行數。 方法executeUpdate 用於執行 INSERT、UPDATE 或 DELETE 語句 以及 SQL DDL(資料定義語言)語句, 例如 CREATE TABLE 和 DROP TABLE。 INSERT、UPDATE 或 DELETE 語句的效果 是修改表中零行或多行中的一列或多列。 executeUpdate 的返回值是一個整數(int), 指示受影響的行數(即更新計數)。 對於 CREATE TABLE 或 DROP TABLE 等 不操作行的語句, executeUpdate 的返回值總為零。 3.booleanexecute(String sql); 可執行任何SQL語句, 返回一個布林值, 表示是否返回ResultSet 。 可用於執行任何SQL語句, 返回一個boolean值, 表明執行該SQL語句是否返回了ResultSet。 如果執行後第一個結果是ResultSet, 則返回true,否則返回false。 但它執行SQL語句時比較麻煩, 通常我們沒有必要使用execute方法 來執行SQL語句, 而是使用executeQuery或executeUpdate更適合, 但如果在不清楚SQL語句的型別時 則只能使用execute方法 來執行該SQL語句了。
100.Statement中的setFetchSize和setMaxRows方法有什麼用處
setMaxRows可以用來限制返回的資料集的行數。 當然通過SQL語句也可以實現這個功能。 比如在MySQL中我們可以用 LIMIT條件來設定返回結果的最大行數。 setFetchSize理解起來就有點費勁了, 因為你得知道Statement 和ResultSet是怎麼工作的。 當資料庫在執行一條查詢語句時, 查詢到的資料是在資料庫的快取中維護的。 ResultSet其實引用的是資料庫中快取的結果。 假設我們有一條查詢返回了100行資料, 我們把fetchSize設定成了10, 那麼資料庫驅動每次只會取10條資料, 也就是說得取10次。 當每條資料需要處理的時間比較長的時候 並且返回資料又非常多的時候, 這個可選的引數就變得非常有用了。 我們可以通過Statement來 設定fetchSize引數, 不過它會被ResultSet物件 設定進來的值所覆蓋掉。