花時間刷完了牛客網專項訓練所有的Java題,終于有點時間,決定肝一篇Java基礎總結,帶你掃清Java基礎面試障礙!


文章目錄
- 1、Java關鍵字
- 2、向上或向下轉型
- 3、類初始化順序
- 4、ASCII碼表
- 5、 權限修飾符
- 6、位運算子
- 7、靜態變數和成員變數的區別
- 8、Java創建物件的方式有幾種?
- 9、值傳遞和參考傳遞
- 10、String和StringBuffer、StringBuilder的區別?
- 11、多載和重寫的區別?
- 12、集合框架中的泛型有什么優點?
- 13、final, finally, finalize的區別?
- 14、Exception和Error的區別?
- 15、throw 和throws 的區別?
- 16、什么是Java反射機制?
- 17、獲取Class 物件的方法?
- 18、什么是Java復制?
- 19、什么是Java序列化?
- 20、為啥要實作Serializable介面?
- 21、Transient 關鍵字有什么作用?
- 22、截止JDK1.8版本,java并發框架支持鎖包括?
- 23、JDK提供的用于并發編程的同步器有哪些?
- 24、HttpServlet容器回應Web客戶請求流程
- 25、內部類的訪問特點
- 26、陣列和集合的區別
- 27、synchronized關鍵字和volatile關鍵字比較?
- 28、以下哪種方式實作的單例是執行緒安全的
- 29、集合結構
- 30、服務端和客戶端的Socker互動
- 31、常用的排序
- 32、如何判斷哪些記憶體需要回收?
- 33、簡述 java 垃圾回識訓制?
- 34、說一下常見的垃圾回收演算法?
- 35、Minor GC 與 Full GC 分別在什么時候發生?
- 36、classload類加載程序?
- 37、類加載器有幾種?
- 38、說一下雙親委派?
- 39、JAVA 中的參考型別?
- 40、HashMap底層原理?
- 41、如何解決HashMap碰撞問題?
1、Java關鍵字

分組一下:
?? 關鍵字一律用小寫字母標識,按其用途劃分為如下幾組,
(1)用于資料型別,
?? 用于資料型別的關鍵字有 boolean、byte、char、 double、 float、int、long、new、short、void、instanceof,
(2)用于陳述句,
?? 用于陳述句的關鍵字有break、case、 catch、 continue、 default 、do、 else、 for、 if、return、switch、try、 while、 finally、 throw、this、 super,
(3)用于修飾
?? 用于修飾的關鍵字有 abstract、final、native、private、 protected、public、static、synchronized、transient、 volatile,
(4)用于方法、類、介面、包和例外,
?? 用于方法、類、介面、包和例外的關鍵字有 class、 extends、 implements、interface、 package、import、throws,
?? 還有些關鍵字,如 future、 generic、 operator、 outer、rest、var等都是Java保留的沒有意義的關鍵字,
另外,Java還有3個保留字:goto、const、null,它們不是關鍵字,而是文字,包含Java定義的值,和關鍵字一樣,它們也不可以作為識別符號使用,
2、向上或向下轉型
Base base = new Son();
base.method();
base.methodB();
記住口訣:編譯看左邊,運行看右邊,
意思是說編譯時候,看左邊有沒有該方法,運行的時候結果看 new 的物件是誰,就呼叫的誰,
3、類初始化順序
class A {
public A() {
System.out.println("class A");
}
{
System.out.println("I'm A class");
}
static {
System.out.println("class A static");
}
}
class B extends A {
public B() {
System.out.println("class B");
}
{
System.out.println("I'm B class");
}
static {
System.out.println("class B static");
}
public static void main(String arg[]) {
new B();
}
}
輸出順序:
class A static
class B static
I'm A class
class A
I'm B class
class B
順序應該是:父類靜態域——>子類靜態域——>父類成員初始化——>父類構造塊——>父類構造方法——>子類成員初始化——>子類構造塊——>子類構造方法;
4、ASCII碼表

5、 權限修飾符

6、位運算子
- &邏輯與:有false則false,
- |邏輯或:有true則true,
- ^邏輯異或:相同為false,不同為true,
- !邏輯非:非false則true,非true則false,
7、靜態變數和成員變數的區別
- A:所屬不同
- 靜態變數屬于類,所以也稱為為類變數
- 成員變數屬于物件,所以也稱為實體變數(物件變數)
- B:記憶體中位置不同
- 靜態變數存盤于方法區的靜態區
- 成員變數存盤于堆記憶體
- C:記憶體出現時間不同
- 靜態變數隨著類的加載而加載,隨著類的消失而消失
- 成員變數隨著物件的創建而存在,隨著物件的消失而消失
- D:呼叫不同
- 靜態變數可以通過類名呼叫,也可以通過物件呼叫
- 成員變數只能通過物件名呼叫
8、Java創建物件的方式有幾種?
(1)使用 new 關鍵字(最常用)
ObjectName obj = new ObjectName();
(2)使用反射的Class類的newInstance()方法
ObjectName obj = ObjectName.class.newInstance();
(3)使用反射的Constructor類的newInstance()方法
ObjectName obj = ObjectName.class.getConstructor.newInstance();
(4)使用物件克隆clone()方法
ObjectName obj = obj.clone();
(5)使用反序列化(ObjectInputStream)的readObject()方法
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
ObjectName obj = ois.readObject();
}
9、值傳遞和參考傳遞
答:值傳遞不可以改變原變數的內容和地址;
參考傳遞不可以改變原變數的地址,但可以改變原變數的內容;
10、String和StringBuffer、StringBuilder的區別?
答:String類是不可變類(final修飾),即一旦一個String物件被創建以后,包含在這個物件中的字符序列是不可改變的,直至這個物件被銷毀,StringBuffer是執行緒安全的,StringBuilder執行緒不安全,但效率高,
實際使用:
如果要操作少量的資料用:String
單執行緒操作字串緩沖區下操作大量資料:StringBuilder
多執行緒操作字串緩沖區下操作大量資料:StringBuffer
11、多載和重寫的區別?
答:多載(Overload):在同一個類中,如果多個方法,名字相同、引數不同,即稱為多載,在編譯器眼里,方法名稱+引數型別+引數個數,組成一個唯一鍵,稱為方法簽名,JVM通過這個唯一鍵決定呼叫哪個多載的方法,
重寫(Override):方法重寫是存在子父類之間的,子類定義的方法與父類中的方法具有相同的名字、引數、回傳型別,
口訣看這里:
方法重寫的記憶口訣“ 一大兩小兩同”
- 一大:子類的方法訪問權限控制符只能相同或變大,
- 兩小:拋出例外和回傳值只能變小, 能夠轉型成父類物件,子類的回傳值、拋出例外型別必須與父類的回傳值、拋出例外型別存在繼承關系,
- 兩同:方法名和引數必須完全相同,
12、集合框架中的泛型有什么優點?
答:泛型提供了編譯時型別安全檢測機制,該機制允許在編譯時檢測到非法的型別,泛型限制了集合容納的物件型別,如果添加其它型別的任何元素,它會在編譯時報錯,這避免了在運行時出現 ClassCastException,泛型也使得代碼整潔,我們不需要使用顯式轉換和 instanceOf 運算子,它也給運行時帶來好處,因為不會產生型別檢查的位元組碼指令,
13、final, finally, finalize的區別?
答:final 用于宣告屬性,方法和類,分別表示屬性不可變,方法不可覆寫,類不可繼承,
內部類要訪問區域變數,區域變數必須定義成final型別,例如,一段代碼……
finally是例外處理陳述句結構的一部分,表示總是執行,
finalize是Object類的一個方法,在垃圾收集器執行的時候會呼叫被回收物件的此方法,可以覆寫此方法提供垃圾收集時的其他資源回收,例如關閉檔案等,JVM不保證此方法總被呼叫,
14、Exception和Error的區別?
答:Exception 和 Error 都是繼承了 Throwable類,在 Java 中只有 Throwable 型別的實體才可以被拋出(throw)或者捕獲(catch),它是例外處理機制的基本組成型別,Exception 和 Error 體現了 Java 平臺設計者對不同例外情況的分類,

Exception:程式正常運行中,可以預料的意外情況,可能并且應該被捕獲,進行相應處理,
Error:是指在正常情況下,不大可能出現的情況,絕大部分的 Error 都會導致程式(比如 JVM 自身)處于非正常的、不可恢復狀態,既然是非正常情況,所以不便于也不需要捕獲,常見的比如OutOfMemoryError之類,都是 Error 的子類,
Exception 又分為可檢查(checked)例外和不檢查(unchecked)例外,
● 可檢查例外在源代碼里必須顯式地進行捕獲處理,這是編譯期檢查的一部分,
● 不檢查例外就是所謂的運行時例外,類似NullPointerException、ArrayIndexOutOfBoundsException之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,并不會在編譯期強制要求,
15、throw 和throws 的區別?
答:位置不同:throws 用在函式上,后面跟的是例外類,可以跟多個;而throw 用在函式內,后面跟的是例外物件,
功能不同:
(1)throws 用來宣告例外,讓呼叫者只知道該功能可能出現的問題,可以給出預先的處理方式;throw 拋出具體的問題物件,執行到throw,功能就已經結束了,跳轉到呼叫者,并
將具體的問題物件拋給呼叫者,也就是說throw 陳述句獨立存在時,下面不要定義其他語
句,因為執行不到,
(2) throws 表示出現例外的一種可能性,并不一定會發生這些例外;throw 則是拋出了例外,執行throw 則一定拋出了某種例外物件,
(3)兩者都是消極處理例外的方式,只是拋出或者可能拋出例外,但是不會由函式去處理例外,真正的處理例外由函式的上層呼叫處理,
16、什么是Java反射機制?
答:Java 中的反射機制是指在運行狀態中,對于任意一個類都能夠知道這個類所有的屬性和方法;并且對于任意一個物件,都能夠呼叫它的任意一個方法;這種動態獲取資訊以及動態呼叫物件方法的功能成為Java 語言的反射機制,
它的功能:
(1)在運行時判定任意一個物件所屬的類;
(2)在運行時構造任意一個類的物件;
(3)在運行時判定任意一個類所具有的成員變數和方法;
(4)在運行時呼叫任意一個物件的方法;
(5)生成動態代理;
17、獲取Class 物件的方法?
答:(1)呼叫某個物件的getClass()方法;
Person p=new Person();
Class clazz=p.getClass();
(2)呼叫某個類的class 屬性來獲取該類對應的Class 物件;
Class clazz=Person.class;
(3)使用Class 類中的forName()靜態方法(最安全/性能最好);
Class clazz=Class.forName("類的全路徑");
18、什么是Java復制?
答:將一個物件的參考復制給另外一個物件,一共有三種方式,
第一種方式是直接賦值,第二種方式是淺拷貝,第三種是深拷貝,
(1)直接賦值
A a1 = a2,實際上復制的是參考,也就是說a1 和a2 指向的是同一個物件,因此,當a1 變化的時候,a2 里面的成員變數也會跟著變化,
(2)淺復制(復制參考但不復制參考的物件)
創建一個新物件,然后將當前物件的非靜態欄位復制到該新物件,如果欄位是值型別的,那么對該欄位執行復制;如果該欄位是參考型別的話,則復制參考但不復制參考的物件,因此,原始物件及其副本參考同一個物件,
(3)深復制(復制物件和其應用物件)
深拷貝不僅復制物件本身,而且復制物件包含的參考指向的所有物件,
19、什么是Java序列化?
答:序列化:將java物件轉換為位元組序列的程序稱為物件的序列化;
在保存物件時,會把其狀態保存為一組位元組,在未來,再將這些位元組組裝成物件,必須注意地是,物件序列化保存的是物件的“狀態”,即它的成員變數,由此可知,物件序列化不會關注類中的靜態變數,
為什么要序列化?
(1)持久化(2)網路傳輸
20、為啥要實作Serializable介面?
答:這個介面其實是個空介面,那么實作它有什么用呢?其實,當我們讓物體類實作Serializable介面時,其實是在告訴JVM此類可被序列化,可被默認的序列化機制序列化,
21、Transient 關鍵字有什么作用?
答:簡而言之,被transient修飾的變數不參與序列化和反序列化,
22、截止JDK1.8版本,java并發框架支持鎖包括?
● 自旋鎖:自旋,jvm默認是10次吧,有jvm自己控制,for去爭取鎖
● 阻塞鎖:被阻塞的執行緒,不會爭奪鎖,
● 可重入鎖:多次進入改鎖的域
● 讀寫鎖
● 互斥鎖:鎖本身就是互斥的
● 悲觀鎖:不相信,這里會是安全的,必須全部上鎖
● 樂觀鎖:相信,這里是安全的,
● 公平鎖:有優先級的鎖
● 非公平鎖:無優先級的鎖
● 偏向鎖:無競爭不鎖,有競爭掛起,轉為輕量鎖
● 物件鎖:鎖住物件
● 執行緒鎖
● 鎖粗化:多鎖變成一個,自己處理
● 輕量級鎖:CAS 實作
● 鎖消除:偏向鎖就是鎖消除的一種
● 鎖膨脹:jvm實作,鎖粗化
● 信號量:使用阻塞鎖 實作的一種策略
● 排它鎖:X鎖,若事務T對資料物件A加上X鎖,則只允許T讀取和修改A,其他任何事務都不能再對A加任何型別的鎖,直到T釋放A上的鎖,這就保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A,
23、JDK提供的用于并發編程的同步器有哪些?
答:(1)Semaphore
?? 可以很輕松完成信號量控制,Semaphore可以控制某個資源可被同時訪問的個數,通過 acquire() 獲取一個許可,如果沒有就等待,而 release() 釋放一個許可,
(2)CyclicBarrier
?? 主要的方法就是一個:await(),await()方法沒被呼叫一次,計數便會減少1,并阻塞住當前執行緒,當計數減至0時,阻塞解除,所有在此 CyclicBarrier 上面阻塞的執行緒開始運行,
(3)CountDownLatch
?? 直譯過來就是倒計數(CountDown)門閂(Latch),倒計數不用說,門閂的意思顧名思義就是阻止前進,在這里就是指 CountDownLatch.await() 方法在倒計數為0之前會阻塞當前執行緒,
24、HttpServlet容器回應Web客戶請求流程
(1)Web客戶向Servlet容器發出Http請求;
(2) Servlet容器決議Web客戶的Http請求;
(3)Servlet容器創建一個HttpRequest物件,在這個物件中封裝Http請求資訊;
(4)Servlet容器創建一個HttpResponse物件;
(5) Servlet容器呼叫HttpServlet的service方法,這個方法中會根據request的Method來判斷具體是執行doGet還是doPost,把HttpRequest和HttpResponse物件作為service方法的引數傳給HttpServlet物件;
(6) HttpServlet呼叫HttpRequest的有關方法,獲取HTTP請求資訊;
(7)HttpServlet呼叫HttpResponse的有關方法,生成回應資料;
(8)Servlet容器把HttpServlet的回應結果傳給Web客戶,
25、內部類的訪問特點
● 內部類可以直接訪問外部類的成員,包括私有,
● 外部類要訪問內部類的成員,必須創建物件,
● 外部類名.內部類名 物件名 = 外部類物件.內部類物件,
26、陣列和集合的區別
(1) 存盤
- 陣列既可以存盤基本資料型別,又可以存盤參考資料型別,基本資料型別存盤的是值,參考資料型別存盤的是地址值,
- 集合只能存盤參考資料型別(物件)集合中也可以存盤基本資料型別,但是在存盤的時候會自動裝箱變成物件,
(2)長度 - 陣列長度是固定的,不能自動增長,
- 集合的長度的是可變的,可以根據元素的增加而增長,
27、synchronized關鍵字和volatile關鍵字比較?
● volatile關鍵字是執行緒同步的輕量級實作,所以volatile性能肯定比synchronized關鍵字要好,但是volatile關鍵字只能用于變數而synchronized關鍵字可以修飾方法以及代碼塊,synchronized關鍵字在JavaSE1.6之后進行了主要包括為了減少獲得鎖和釋放鎖帶來的性能消耗而引入的偏向鎖和輕量級鎖以及其它各種優化之后執行效率有了顯著提升,實際開發中使用 synchronized 關鍵字的場景還是更多一些,
● 多執行緒訪問volatile關鍵字不會發生阻塞,而synchronized關鍵字可能會發生阻塞,
● volatile關鍵字能保證資料的可見性,但不能保證資料的原子性,synchronized關鍵字兩者都能保證,
● volatile關鍵字主要用于解決變數在多個執行緒之間的可見性,而 synchronized關鍵字解決的是多個執行緒之間訪問資源的同步性,
28、以下哪種方式實作的單例是執行緒安全的
● 餓漢式(執行緒安全,呼叫效率高,但是不能延時加載);
● 懶漢式(執行緒安全,呼叫效率不高,但是能延時加載);
● Double CheckLock實作單例:DCL也就是雙重鎖判斷機制(由于JVM底層模型原因,偶爾會出問題,不建議使用);
● 靜態內部類實作模式(執行緒安全,呼叫效率高,可以延時加載);
● 列舉類(執行緒安全,呼叫效率高,不能延時加載,可以天然的防止反射和反序列化呼叫),
29、集合結構

30、服務端和客戶端的Socker互動

public class TcpServer {
public static void main(String[] args) throws Exception {
// Server端監聽10000埠
ServerSocket serverSocket = new ServerSocket(10000);
while(true){
// 等待客戶端連接,此時進入阻塞狀態
Socket socket = serverSocket.accept();
System.out.println("Connected: " + socket.getRemoteSocketAddress());
// 從Socket讀取資料
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int length = inputStream.read(b);
System.out.println(length + " Bytes Received");
}
}
}
public class TcpClient {
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//1.建立TCP連接
Socket client = null;
try {
client = new Socket("127.0.0.1", 10006);
client.setSoTimeout(10000);
}catch (Exception e){
throw new Exception("TCP連接例外");
}
//2、傳輸內容
String content = "這是一個JAVA模擬客戶端";
byte[] bstream = content.getBytes("UTF-8");//位元組流
OutputStream os = client.getOutputStream();
os.write(bstream);
//3、關閉TCP連接
if (null != client ){
client.close();
}
}
}
31、常用的排序

32、如何判斷哪些記憶體需要回收?
答:(1)參考計數(存盤在堆物件資料里面(物件頭)):一個物件被參考一次,那么應用計數就加1,如果說沒有參考,減1 參考計數等于0,就表示這個物件需要回收,(有回圈參考問題)
(2)可達性分析法:這個演算法的基本思想是通過一系列稱為“GC Roots”的物件作為起始點,從這些節點向下搜索,搜索所走過的路徑稱為參考鏈,當一個物件到GC Roots沒有任何參考鏈(即GC Roots到物件不可達)時,則證明此物件是不可用的,(注意:不可達物件不等價于可回收物件,不可達物件變為可回收物件至少要經過兩次標記程序,兩次標記后仍然是可回收物件,則將面臨回收,)
33、簡述 java 垃圾回識訓制?
答:在 java 中,程式員是不需要顯示的去釋放一個物件的記憶體的,而是由虛擬機自行執行,在JVM 中,有一個垃圾回收執行緒,它是低優先級的,在正常情況下是不會執行的,只有在虛擬機空閑或者當前堆記憶體不足時,才會觸發執行,掃面那些沒有被任何參考的物件,并將它們添加到要回收的集合中,進行回收,
34、說一下常見的垃圾回收演算法?
答:(1)標記-清除演算法(年老代)
產生大量的記憶體碎片,效率也不高,適用于存活物件較多的情況下比較高效,適用于年老代(即舊生代),
(2)復制演算法(新生代)
時間換空間,解決了效率問題,但浪費了空間,適用于存活物件較少的情況下比較高效,適用于年輕代(即新生代),
(3)標記-整理演算法(年老代)
解決物件都存活的問題,是標記-清除演算法的優化,將所有的存活物件壓縮到記憶體的一端,之后,清理邊界外所有的空間,適用于年老代(即舊生代),
(4)分代收集演算法
分代收集演算法是目前大部分JVM的垃圾收集器采用的演算法,它的核心思想是根據物件存活的生命周期將記憶體劃分為若干個不同的區域,一般情況下將堆區劃分為老年代(Tenured Generation)和新生代(Young Generation),在堆區之外還有一個代就是永久代(Permanet Generation),新生代的特點是每次垃圾回收時都有大量的物件需要被回收,那就選用復制演算法,只需要付出少量存活物件的復制成本就可以完成收集,而老年代的特點是每次垃圾收集時只有少量物件需要被回收,物件存活率高,就可使用“標記-清理”或“標記-整理”演算法來進行回收,
35、Minor GC 與 Full GC 分別在什么時候發生?
答:新生代記憶體不夠用時候發生 MGC 也叫 YGC,JVM 記憶體不夠的時候發生 FGC
36、classload類加載程序?
答:JVM類加載機制分為五個部分:加載,驗證,準備,決議,初始化,下面我們就分別來看一下這五個程序,
(1)加載
將class位元組碼檔案加載到記憶體中,通過一個類的全限定名獲取該類的二進制流,并將該二進制流中的靜態存盤結構轉換成方法區中的運行時資料(靜態變量、靜態代碼塊、常量池等),在堆中生成一個Class類物件代表這個類(反射原理),作為方法區類資料的訪問入口,
(2)驗證
確保加載的類資訊符合JVM規范,沒有安全方面的問題,
● 檔案格式驗證:驗證位元組流是否符合 Class 檔案的規范,如主次版本號是否在當前虛擬機范圍內,常量池中的常量是否有不被支持的型別.
● 元資料驗證:對位元組碼描述的資訊進行語意分析,如這個類是否有父類,是否集成了不被繼承的類等,
● 位元組碼驗證:是整個驗證程序中最復雜的一個階段,通過驗證資料流和控制流的分析,確定程式語意是否正確,主要針對方法體的驗證,如:方法中的型別轉換是否正確,跳轉指令是否正確等,
● 符號參考驗證:這個動作在后面的決議程序中發生,主要是為了確保決議動作能正確執行,
(3)準備
正式為類變數(static變數)分配記憶體并設定類變數初始值的階段,這些記憶體都將在方法區中進行分配,注意此時的設定初始值為默認值,具體賦值在初始化階段完成,
(4)決議
虛擬機常量池內的符號參考替換為直接參考(地址參考)的程序,
(5)初始化
初始化階段對靜態變數和靜態代碼塊執行初始化作業,到了初始化階段,才真正開始執行類中定義的Java 程式代碼,
初始化順序:父類的靜態變數->父類的靜態代碼塊->子類的靜態變數->子類的靜態代碼塊->父類的非靜態變數->父類的非靜態代碼塊->父類的構造方法->子類的非靜態變數->子類的非靜態代碼塊->子類的構造方法,
37、類加載器有幾種?
答:(1)啟動類加載器(Bootstrap ClassLoader)
負責加載加載 Java 核心類別庫,無法被 Java 程式直接參考, 在JAVA_HOME\lib 目錄中的,或通過-Xbootclasspath引數指定路徑中的,且被虛擬機認可(按檔案名識別,如rt.jar)的類,
(2)擴展類加載器(Extension ClassLoader)
負責加載Java的擴展庫,在 JAVA_HOME\lib\ext 目錄中的,或通過java.ext.dirs系統變數指定路徑中的類別庫,
(3)應用程式類加載器(Application ClassLoader)
負責加載用戶路徑(classpath)上的類別庫, JVM通過雙親委派模型進行類的加載,當然我們也可以通過繼承java.lang.ClassLoader實作自定義的類加載器,

38、說一下雙親委派?
答:當一個類收到了類加載請求,他首先不會嘗試自己去加載這個類,而是把這個請求委派給父類去完成,每一個層次類加載器都是如此,因此所有的加載請求都應該傳送到啟動類加載其中,只有當父類加載器反饋自己無法完成這個請求的時候(在它的加載路徑下沒有找到所需加載的Class),子類加載器才會嘗試自己去加載,
?? 有什么好處:
(1)基于雙親委派模型規定的這種帶有優先級的層次性關系,虛擬機運?程式時就能夠避免類的重復加載,
(2)雙親委派模型能夠避免核?類篡改,
39、JAVA 中的參考型別?
答:(1)強參考
在Java中最常見的就是強參考,把一個物件賦給一個參考變數,這個參考變數就是一個強參考,當一個物件被強參考變數參考時,它處于可達狀態,它是不可能被垃圾回識訓制回收的,即使該物件以后永遠都不會被用到JVM也不會回收,因此強參考是造成Java記憶體泄漏的主要原因之一,
(2)軟參考
軟參考需要用SoftReference類來實作,對于只有軟參考的物件來說,當系統記憶體足夠時它不會被回收,當系統記憶體空間不足時它會被回收,軟參考通常用在對記憶體敏感的程式中,
(3)弱參考
弱參考需要用WeakReference類來實作,它比軟參考的生存期更短,對于只有弱參考的物件來說,只要垃圾回識訓制一運行,不管JVM的記憶體空間是否足夠,總會回收該物件占用的記憶體,
(4)虛參考
虛參考需要PhantomReference類來實作,它不能單獨使用,必須和參考佇列聯合使用,虛參考的主要作用是跟蹤物件被垃圾回收的狀態,
40、HashMap底層原理?
答:博文鏈接:一文看懂HashMap底層原理
41、如何解決HashMap碰撞問題?
答:(1)開放地址法
開放地執法有一個公式:Hi=(H(key)+di) MOD m i=1,2,…,k(k<=m-1)
基本思想:當發生地址沖突時,按照某種方法繼續探測哈希表中的其他存盤單元,直到找到空位置為止,
(2)鏈地址法(拉鏈法)
創建一個鏈表陣列,陣列中每一格就是一個鏈表,若遇到哈希沖突,則將沖突的值加到鏈表中即可,
java hashmap使用的就是拉鏈法解決hash碰撞,
覺得不錯的,感謝點贊支持!后續再補充一些,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/316605.html
標籤:java
上一篇:初識Java--資料型別和運算子
下一篇:力扣牛客之十大鏈表必刷題
