cvte面試題收集
- 什麼樣的物件可以當作gcroots
在Java語言裡,可作為GC Roots物件的包括如下幾種:
a.虛擬機器棧(棧楨中的本地變量表)中的引用的物件
b.方法區中的類靜態屬性引用的物件
c.方法區中的常量引用的物件
d.本地方法棧中JNI的引用的物件
https://blog.csdn.net/bolg_hero/article/details/79344745
- switch能否用string做引數
- 在jdk 7 之前,switch 只能支援 byte、short、char、int 這幾個基本資料型別以及由於1.5之後的自動拆箱,這四種基礎型別對應的封裝類也同樣支援Byte,Short,Character,Integer。
Integer num = new Integer(1);
switch (num){
case 1:
System.out.println("1");break;
case 2:
System.out.println("2");break;
}
當Integer與int比較時,會自動拆箱,轉成int型別進行比較。
但如果兩個都是Integer型別,就不會自動拆箱成int型別,直接是以Integer型別比較,所以這裡有個難理解的點就是,
Integer num1 = 1;
Integer num2 = 1;
if (num1 == num2){
System.out.println(true);
}else{
System.out.println(false);
}
Integer num3 = 166;
Integer num4 = 166;
if (num3 == num4){
System.out.println(true);
}else {
System.out.println(false);
}
輸出結果
true
false
結果是不是意料之外?為什麼num1 == num2,但num3 != num4 ?
因為,在自動裝箱時,對於值從–128到127之間的值,它們被裝箱為Integer物件後,會存在記憶體中被重用,始終只存在一個物件;而如果超過了從–128到127之間的值,被裝箱後的Integer物件並不會被重用,即相當於每次裝箱時都新建一個 Integer物件;
- 在jdk1.7後,整形,列舉型別,boolean,字串都可以
-
SpringMVC執行流程
第一步
使用者發起請求到前端控制器DispatcherServlet
第二步
DispatcherServlet請求處理器對映器HandlerMapping查詢Handler
可以是根據xml查詢,也可以是根據註解查詢
第三步
HandlerMapping向DispatcherServlet返回Handler
第四步
HandlerMapping呼叫處理器介面卡HandlerAdapter去執行Handler
第五步
處理器介面卡去執行Handler
第六步
Handler執行完給處理器介面卡返回ModelAndView
ModelAndView是SpringMVC框架的一個底層物件,包括Model和View
第七步
處理器介面卡給DispatcherServlet返回ModelAndView
第八步
DispatcherServlet請求檢視解析器View resolver進行檢視解析
根據邏輯檢視解析成真正的物理檢視(jsp等)
第九步
檢視解析器向DispatcherServlet返回view
第十步
DispatcherServlet進行檢視渲染
第十一步
DispatcherServlet向用戶響應結果
原文:https://blog.csdn.net/leisure_life/article/details/72793738 -
淺談Session與Cookie的區別與聯絡
https://blog.csdn.net/bwh0520/article/details/78808181 -
hashmap相關的問題
- 5.1 hashmap原始碼 https://blog.csdn.net/ooo123lll/article/details/81103234#335-get
- 5.1 hashmap擴容、為什麼是2n(2的n次方)擴容 https://www.cnblogs.com/williamjie/p/9358291.html
擴容或者初始化容量時,都是以2的n次方擴容,這主要原因是,hashmap定位key的下標的機制決定的。根據原始碼:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
// 若“key不為null”,則計算該key的雜湊值,然後將其新增到該雜湊值對應的連結串列中。
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
// 若“該key”對應的鍵值對已經存在,則用新的value取代舊的value。然後退出!
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
// 若“該key”對應的鍵值對不存在,則將“key-value”新增到table中
modCount++;
addEntry(hash, key, value, i);
return null;
}
// 返回索引值
// h & (length-1)保證返回值的小於length
static int indexFor(int h, int length) {
return h & (length-1);
}
我們可以看到當put或者get方法時,會先對key進行hashcode獲得hash值,然後用hash值和(table長度-1)進行與運算(indexFor方法),從而得到key的table陣列的下標,其實除了與運算,還可以直接使用mod取餘運算(hash值%(table長度-1))來獲得下標位置,但由於在計算機中取餘運算很耗時(計組中有學二進位制的除法運算會比二進位制的直接與運算複雜很多),所以hashmap採用的是運算來定位key的下標。
如果table長度是2的n次方,那麼table.length-1的二進位制一定是都是1,如length=16,則length-1=15 -> 1111
那麼任何一個小於table.length-1的數字跟length-1進行與運算都是它本身,如9->1001,1001 & 1111 = 1001;這樣能保證key的分步均勻,減少key的衝突。
但如果不是2的n次方,假設table.length=15,則table.length-1=14 -> 1110,key的hash值認為9,即1001 & 1110 = 1000 ,發現了什麼?只要key的hash值的二進位制位1的都不能 用了,這樣會跟原本應該在***0的位置的key產生衝突,然後hashmap使用的是拉鍊法解決衝突,所以衝突的key會放到連結串列中,無衝突的hashmap取值的時間複雜度為O(1),如果衝突,則在連結串列中查詢當前值的時間複雜度為O(n),這嚴重降低了hashmap的查詢料率。
所以不管是在初始化容量時還是在擴容時,jdk會自動幫你選擇以2den次方進行擴容。
-
5.2 負載因子為什麼是0.75 https://www.cnblogs.com/peizhe123/p/5790252.html
當建立 HashMap 時,有一個預設的負載因子(load factor),其預設值為 0.75,這是時間和空間成本上一種折衷:增大負載因子可以減少 Hash 表(就是那個 Entry 陣列)所佔用的記憶體空間,但會增加查詢資料的時間開銷,而查詢是最頻繁的的操作(HashMap 的 get() 與 put() 方法都要用到查詢);減小負載因子會提高資料查詢的效能,但會增加 Hash 表所佔用的記憶體空間。 -
5.3 hashMap為什麼執行緒不安全(hash碰撞與擴容導致)https://www.cnblogs.com/qiumingcheng/p/5259892.html
-
5.4 hashmap衝突的解決方法以及原理分析:https://www.cnblogs.com/peizhe123/p/5790252.html