1.深入解讀:JDK與JRE的區別
JDK提供了完整的Java開發工具和資源,包括編譯器、調試器和其他開發工具,滿足開發人員的各種需求。
JRE則相對更為基礎,它只提供了Java程序運行所需的環境,包含了Java虛擬機(JVM)和Java核心類庫,不包含開發工具。在部署Java應用程序時,只需要安裝JRE來運行程序即可。
JDK< JRE , 開發工具 >
JRE< JVM , 核心類庫 >
2.Java 中 boolean 占多少字節?
《Java 虛擬機規范》提議:
如果 boolean 是 “單獨使用”:boolean 被編譯為 int 類型,占 4 個字節;
如果boolean 是以 “boolean 數組” 的形式使用:boolean 占 1 個字節,Java 虛擬機直接支持 boolean 數組,通過 newarray 指令創建 boolean 數組,然后通過 byte 數組指令 baload 和 bastore 來訪問和修改 boolean 數組。
但是,具體占用大小仍然取決于每個虛擬機的具體實現是否按照規范來
其他基本數據類型占用字節數
char:2B;
byte-short-int- long:1-2-4-8B;
float-double:4-8B
3.用最有效率的方法計算 2 乘以 8
2 << 3。位運算,數字的二進制位左移三位相當于乘以 2 的三次方。
4.為什么重寫equals時必須重寫hashcode方法
Object 的 hashcode 方法是本地方法,該方法直接返回對象的內存地址。如果沒有重寫hashCode(),則任何對象的hashCode()值都不相等。如果只重寫equals沒有重寫hashCode(),就會導致相同的key值也被hashcode認為是不同的key值
5.為什么Java字符串是不可變的?有什么好處?
String 類被 final 關鍵字修飾,這就意味著沒有子類可以重寫它的方法。
String 類內部使用一個私有的字符數組來存儲字符串數據。這個字符數組在創建字符串時被初始化,之后不允許被改變。
好處:
-保證 String 對象的安全性,避免被篡改;
-保證哈希值不會頻繁變更。以哈希表的鍵值來說,經常變更的話,哈希表的性能會下降。在 String 類中,哈希值是在第一次計算時緩存的,后續對該哈希值的請求將直接使用緩存值;
-實現字符串常量池,Java 會將相同內容的字符串存儲在字符串常量池中。這樣,具有相同內容的字符串變量可以指向同一個 String 對象,節省內存空間。
6.Integer類的緩存機制
IntegerCache: Integer 類內部中內置了 256 個 Integer 類型的緩存數據,數據范圍在 -128~127 之間。超過此范圍,要比較Integer對象的數值是否相等,應該使用equals方法,而不是==運算符。
.
通過 Integer.valueOf() 方法獲取整數對象時,會先檢查該整數是否在 IntegerCache 中,如果在,則返回緩存中的對象,否則創建一個新的對象并緩存起來。
如果使用 new Integer() 創建對象,即使值在 -128 到 127 范圍內,也不會被緩存,每次都會創建新的對象。【比如new Integer(10) == new Integer(10) :false】因此,推薦使用 Integer.valueOf() 方法獲取整數對象。
.
相關補充:String 轉成 Integer,主要有兩個方法:Integer.parseInt(String s)、Integer.valueOf(String s)
7.異常
Throwable 是 Java 語言中所有錯誤和異常的基類。它有兩個主要的子類:Error 和 Exception。
Error 類代表那些嚴重的錯誤,這類錯誤通常是程序無法處理的。比如,OutOfMemoryError 表示內存不足,StackOverflowError 表示棧溢出。這些錯誤通常與 JVM 的運行狀態有關,一旦發生,應用程序通常無法恢復。
Exception 類代表程序可以處理的異常。它分為兩大類:編譯時異常 和 運行時異常。
編譯時異常在編譯時必須被顯式處理(捕獲或聲明拋出),比如IOException、SQLException 等。
運行時異常在運行時拋出,通常是由程序邏輯錯誤導致的,如 NullPointerException、ArrayIndexOutOfBoundsException 等。
NoClassDefFoundError 和 ClassNotFoundException 有什么區別
它們都是由于系統運行時找不到要加載的類導致的,但是觸發的原因不一樣。
NoClassDefFoundError:當JVM在加載一個類的時候,這個類在編譯時是可用的,但是在運行時找不到這個類的定義。原因可能是 jar 包缺失或者調用了初始化失敗的類。
ClassNotFoundException:當應用程序運行的過程中嘗試使用類加載器去加載Class文件的時候,沒有在classpath中查找到指定的類。原因可能是要加載的類不存在或者類名寫錯了。
異常的處理主要有兩種方式:拋出(throw,throws) 和捕獲(try{} catch(){} finally{})
throw 和 throws 的區別
1)throws 關鍵字用于聲明異常;而 throw 關鍵字用于顯式的拋出異常。
2)throws 關鍵字后面跟的是異常的名字;而 throw 關鍵字后面跟的是異常的對象。
3)throws 關鍵字出現在方法簽名上,而 throw 關鍵字出現在方法體里。
4)throws 關鍵字在聲明異常的時候可以跟多個,用逗號隔開;而 throw 關鍵字每次只能拋出一個異常。
try 里的 return 先執行還是 finally 先執行?
finally 先執行。但是,在執行 finally 之前,JVM 會先將 return 的結果暫存起來,即使 finally 修改了 return 的變量值,返回值也不會改變。
8.BIO、NIO、AIO
BIO(Blocking I/O):阻塞 I/O,基于流模型。線程在執行 I/O 操作時被阻塞,無法處理其他任務,適用于連接數較少的場景。
NIO(New I/O 或 Non-blocking I/O):非阻塞 I/O ,基于通道和緩沖區。線程在等待 I/O 時可執行其他任務,適用于連接數多但連接時間短的場景。NIO 的魅力主要體現在網絡編程中,服務器可以用一個線程處理多個客戶端連接,通過 Selector 監聽多個 Channel 來實現多路復用,極大地提高了網絡編程的性能。
AIO(Asynchronous I/O):異步 I/O ,引入了異步通道的概念,基于事件和回調機制。線程發起 I/O 請求后立即返回,當 I/O 操作完成時通過回調函數通知線程,適用于連接數多且連接時間長的場景。
補充:既然有了字節流,為什么還要有字符流?
其實字符流是由 Java 虛擬機將字節轉換得到的,問題就在于這個過程比較耗時,并且,如果我們不知道編碼類型就很容易出現亂碼問題。所以, I/O 流就干脆提供了一個直接操作字符的接口。
在計算機中,文本和視頻都是按照字節存儲的,只是如果是文本文件的話,我們可以通過字符流的形式去讀取,這樣更方面的我們進行直接處理。
9.序列化和反序列化
serialVersionUID 是標識類版本的唯一標識符,確保在序列化和反序列化過程中類的版本是兼容的;
Serializable接口用于標記一個類可以被序列化;
序列化只會保存對象的狀態,因此不包含靜態變量;
可以使用 transient 關鍵字修飾不想序列化的變量;
10.Java反射
反射就是在運行時才知道要操作的類是什么,并且可以在運行時獲取類的完整構造,并調用對應的方法。
反射的原理:Java 程序的執行分為編譯和運行兩步,編譯之后會生成字節碼(.class)文件,JVM 進行類加載的時候,會加載字節碼文件,將類型相關的所有信息加載進方法區,反射就是去獲取這些信息,然后進行各種操作。