Java 面試
1、ArrayList和LinkedList的區別
2、@Autowired和@Resource的主要區別
3、集合
4、mysql索引失效的幾種情況
5、string,stringbuffer、stringbulider的區別
6、&和&&的區別
7、sql的執行順序
8、設計模式
9、五大原則
10、垃圾回收算法
11、Lock 接口實現類
1、ArrayList和LinkedList的區別
ArrayList:
底層數據結構:
ArrayList基于數組實現,元素在內存中連續存儲,支持隨機訪問(時間復雜度為o(1));
LinkedList基于雙向鏈表實現,節點離散存儲并通過指針關聯,不支持隨機訪問(時間復雜度為O(n));
隨機訪問:
ArrayList通過索引直接訪問元素;
LinkedList需遍歷鏈表,效率較低;
插入、刪除:
ArrayList在末尾插入/刪除效率較高(時間復雜度O(1)),中間插入/刪除需移動后續元素,(時間復雜度O(n));
LinkedList在任意位置插入/刪除僅需修改節點指針引用,效率較高(時間復雜度O(1)),但需遍歷鏈表定位節點。 ?
擴容機制:arrayList默認容量不足時自動擴容為原容量的1.5倍,LinkedList無需擴容
- ?優先選擇ArrayList?:當需要頻繁隨機訪問元素或尾部操作較多時(如排行榜、購物車等)。 ?
- ?優先選擇LinkedList?:當需要頻繁在中間或首尾插入/刪除元素時。 ?
2、@Autowired和@Resource的主要區別
1-- @Autowired是spring框架,@Resource是Java標準注解;
2-- @Autowired優先于按照類型(bytype)匹配,然后名稱匹配(byname),沖突時需顯式指定@qualifier;
@Resource優先于按照名稱(byname)進行匹配,然后按照類型(bytype)進行匹配;
3-- @Autowired支持構造方法注入、屬性注入、setter方法注入、方法參數注入
@Resource僅支持屬性方法與setter方法注入,使用構造方法注入會報錯。
3、集合
1.collection
list(有序集合,可以包含重復元素,允許插入null元素) : arrayList(動態數組)、linkedList(雙向鏈表)
set (無序集合,不包含重復元素):hashSet(不保證元素的順序)、linkedHashSet(保持元素的插入順序)
2、map(用于存儲鍵值對)
hashMap(允許使用空值和空鍵)、LinkedHashMap(維護插入順序或者訪問順序)
4、mysql索引失效的幾種情況
---1 索引列參與了計算:查詢條件中對索引列進行了數學運算、函數操作或者其他非索引列的操作
---2 索引列使用了函數
---3 隱式類型轉換 :比較列類型和比較值類型不匹配時,mysql會進行類型轉換
---4 使用通配符like
---5 or條件中的列沒有被索引:使用or連接多個條件時,如果每個條件中的列都沒有被索引,那么整個查詢都沒有被索引
---6 復合索引的不正確使用:如果查詢條件沒有從索引的最左列開始,那么mysql可能不會使用該復合索引
5、string,stringbuffer、stringbulider的區別
String
- ?不可變?:每次修改都會生成新對象,導致內存浪費。 ?
- ?線程安全?:不可變特性使其天然具備線程安全性。 ?
- ?適用場景?:存儲常量、作為方法參數傳遞等不需要修改的場景。 ?
StringBuffer
- ?可變?:支持內容修改,方法同步(線程安全)。 ?
- ?性能?:因同步機制,性能較低,適合多線程環境。 ?
- ?適用場景?:多線程環境下需要頻繁修改字符串(如日志處理)。 ?
StringBuilder
- ?可變?:支持內容修改,非線程安全。 ?
- ?性能?:無同步開銷,效率更高,適合單線程。 ?
- ?適用場景?:單線程中頻繁拼接字符串(如循環生成動態文本)。?
6、&和&&的區別
& 和 && 的核心區別在于短路特性:&& 具有短路功能(若左側表達式為假則跳過右側計算),
& 無論左側結果如何都會計算右側表達式;此外,& 還支持位運算,而 && 僅用于邏輯運算。??
7、sql的執行順序
JOIN:根據指定的條件,將兩個或多個表合并為一個結果集。
WHERE:對查詢結果進行篩選,只保留滿足指定條件的行。
GROUP BY:將結果集按照指定的列進行分組。
WITH ROLLUP:按照GROUP BY的列對結果集進行匯總,并添加一行用于總計或小計。
HAVING:對分組后的結果進行篩選,只保留滿足指定條件的分組。
SELECT:選擇要查詢的列。
DISTINCT:對查詢結果進行去重。
UNION:將兩個或多個查詢結果集合并為一個結果集。
ORDER BY:按照指定的列對結果集進行排序。
LIMIT:指定查詢結果的行數限制。
9、五大原則
SOLID 原則
-
S - 單一職責原則:一個類應該只有一個引起變化的原因。
-
O - 開放封閉原則:軟件實體應該對擴展開放,對修改關閉。
-
L - 里氏替換原則:子類必須能夠替換掉它們的父類。
-
I - 接口隔離原則:不應該強迫客戶依賴于它們不用的方法。
-
D - 依賴倒置原則:要依賴于抽象,不要依賴于具體實現。
10、垃圾回收算法
垃圾回收算法是自動管理內存的機制,用于回收不再使用的對象所占用的內存空間。以下是常見的垃圾回收算法及其原理:
引用計數法
- 原理:通過記錄對象的引用次數,當引用計數為0時回收對象。
- 優點:實現簡單,回收效率高。
- 缺點:無法處理循環引用,計數器開銷大。 ?
標記-清除算法
- 原理:分為標記和清除兩階段,標記存活對象后清除未標記對象。
- 適用場景:存活對象較多的老年代。
- 缺點:易產生內存碎片,需掃描整個空間兩次。 ?
復制算法
- 原理:將存活對象復制到新內存區域,并清空原區域。
- 適用場景:存活對象較少的新生代。
- 缺點:需要額外內存空間,需復制對象。 ?
標記-整理算法
- 原理:標記存活對象后將其壓縮到內存一端,清理邊界外空間。
- 適用場景:老年代,避免碎片且無需額外內存。 ?
分代收集算法
- 原理:將堆分為新生代和老年代,分別采用復制算法和標記-整理算法。
- 優點:結合不同算法優勢,提高回收效率。
11、Lock 接口實現類
在Java中,Lock接口是java.util.concurrent.locks包的一部分,提供了比使用synchronized方法和語句更靈活的線程同步機制。Lock接口的實現類提供了比內置的同步機制更多的功能,例如嘗試非阻塞地獲取鎖、嘗試在給定的等待時間內獲取鎖、以及在釋放鎖之前執行一些清理操作等。
-
-
以下是Java中一些常見的
Lock接口實現類的例子:-
?ReentrantLock?
ReentrantLock是最常用的Lock實現類之一。它實現了Lock接口,支持重進入(reentrant),意味著在同一個線程中可以多次獲取鎖。- 示例代碼:
import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { private final ReentrantLock lock = new ReentrantLock(); public void criticalSection() { lock.lock(); try { // 保護的代碼塊 } finally { lock.unlock(); } } }
-
?ReentrantReadWriteLock?
ReentrantReadWriteLock是一種讀寫鎖實現,允許多個讀線程同時訪問,但寫線程在訪問時需要獨占訪問權。它包含了一對鎖:一個用于讀操作,一個用于寫操作。- 示例代碼:
import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReentrantReadWriteLockExample { private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock(); private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock(); public void read() { readLock.lock(); try { // 讀取操作 } finally { readLock.unlock(); } } public void write() { writeLock.lock(); try { // 寫入操作 } finally { writeLock.unlock(); } } }
-
?StampedLock?
StampedLock是Java 8中引入的一種樂觀讀鎖,它提供了比讀寫鎖更靈活的鎖定模式。它可以用于讀操作,也可以用于寫操作,并且支持樂觀讀(即非阻塞讀)。- 示例代碼:
import java.util.concurrent.locks.StampedLock; public class StampedLockExample { private final StampedLock stampedLock = new StampedLock(); private int value = 0; public void write(int newValue) { long stamp = stampedLock.writeLock(); // 獲取寫鎖 try { value = newValue; // 執行寫操作 } finally { stampedLock.unlockWrite(stamp); // 釋放寫鎖 } } public int read() { long stamp = stampedLock.readLock(); // 獲取讀鎖(樂觀讀) try { return value; // 讀取數據 } finally { stampedLock.unlockRead(stamp); // 釋放讀鎖(樂觀讀) } } }
選擇哪種鎖取決于你的具體需求,例如是否需要公平性、是否需要重入性、是否需要讀寫分離等。每種鎖都有其特定的使用場景和性能特點。通常,
ReentrantLock是最通用和最靈活的選擇,而ReentrantReadWriteLock適合于讀多寫少的場景。StampedLock則提供了一種更高級的樂觀讀鎖定。 -
-

浙公網安備 33010602011771號