前言:
這是下篇,上篇鏈接在下面!
一. 類加載機制
1. 類加載過程
1.1 加載
查找和導入class文件。
1.2 鏈接
- 驗證:檢驗載入的class文件的正確性,完整性。
- 準備:給類的靜態變量分配存儲空間,會賦對象類型的默認值。
- 解析:將class常量池中的符號引用轉換成直接引用。
符號引用和直接引用的區別:
- 符號引用:java編譯階段不知道所引用的對象的實際地址,使用符號引用來代替
- 直接引用:能夠直接定位到對象的指針,或相對偏移量。能定位到一個對象的內存實際地址。
1.3 初始化
對類的靜態變量,代碼塊執行初始化操作,靜態變量賦值順序根據代碼定義的順序執行。
2. 類的加載順序
- 父類靜態成員變量
- 父類靜態代碼塊
- 子類靜態成員變量
- 子類靜態代碼塊
- 父類非靜態成員變量
- 父類非靜態代碼塊
- 父類構造方法
- 子類非靜態成員變量
- 子類非靜態代碼塊
- 子類構造方法
3. 類加載時機
- 創建類實例-使用new關鍵字,反射,克隆,反序列化。
- 調用類的靜態變量或者靜態方法,或對靜態變量進行賦值操作。
- 初始化子類時會先初始化父類。
- 虛擬機啟時,包含main方法的啟動類。
注意:
**通過數組定義的引用類,不會造成類的初始化。
**訪問類的靜態常量是不會造成類加載的。因為在編譯時期,靜態常量已經放入類的常量池中了。訪問類靜態常量其實是直接訪問常量池中的常量,不需要加載類。
4. 靜態常量是什麼時候賦值的
靜態常量在編譯階段把初始值存入class文件的常量池中,在類的準備階段,將值賦給靜態變量。
5. 什麼是雙親委派
- 類加載器包括:BootstrapClassLoader、ExtensionClassLoader、 ApplicationClassLoader、自定義的類加載器。
- 雙親委派模型:如果一個類加載器收到了加載類的請求,首先交給父類加載器進行加載,如果父類加載器加載失敗,當前類才會自己加載類。
- 雙親委派的作用:避免重複加載,父類已經加載子類不用加載,防止用戶自定義加載器加載java核心的api,帶來安全隱患。
- 一個類是否被加載是通過全類名和命名空間確定的,命名空間是加載類的加載器名。
6. 如何自定義類加載器
繼承classloader類,重寫findClass方法。
二. Web與網絡
1. 轉發與重定向的區別
- 轉發是服務器請求資源,服務器直接訪問目標地址url,把響應內容返回給瀏覽器。 重定向根據服務器返回的狀態碼重新請求地址。
- 轉發是服務器行為,重定向是客戶端行為。
- 轉發顯示的url不變而重定向顯示新的url。
- 轉發頁面和轉發到的頁面共享request的信息,重定向不共享數據。
- 轉發一般用於用戶登錄,根據角色轉發到響應的模塊, 重定向一般用於用戶註銷,跳轉到其他的地方。
2. TCP三次握手
建立連接時進行TCP三次握手:
- 客戶端發送syn給服務端 連接請求。
- 服務端發送syn ack 給客戶端 授予連接。
- 客戶端發送ack給服務端 確認連接。
第一次客戶端確認自己的發送正常,服務端確認自己的接收正常。
第二次服務端確認自己的發送,接收正常,客戶端的發送正常。客戶端確認自己的發送、接受正常,服務端的發送、接受正常。
第三次客戶端服務端都確認雙方的發送接收正常。
3. TCP四次揮手
- 客戶端發送fin給服務端,關閉客戶端到服務端的數據傳送。
- 服務端發送ack 。
- 服務端發送fin,關閉服務端和客戶端的連接。
- 客戶端發送ack,連接關閉。
4. 為什麼是三次握手四次揮手
建立連接的時候,syn和ack可以同時發送,但是斷開連接的時候fin和ack不能同時發送,因為server還未確認是否所有的報文都發送完了,所有的報文發送完了才能發送fin。所以建立連接需要三次握手,斷開連接需要四次揮手。
5. TCP與UDP的區別
- TCP協議是有連接的,必須通過三次握手建立連接,UDP是無連接的。
- TCP保證數據按序到達,UDP不能保證。
- TCP是面向字節流的服務,UDP是面向報文的服務。
6. 什麼是Servlet
是http請求和程序之間的中間層。可以讀取客戶端請求數據,處理數據並生成結果。
7. 攔截器與過濾器的區別
- 攔截器基於java反射實現,過濾器基於函數回調。
- 攔截器不依賴Servlet容器,過濾器依賴Servlet。
實現一個攔截器繼承HandlerIntecepterAdapter。
實現過濾器繼承Filter,在web.xml中進行配置。
8. HTTPS的過程
- 客戶端發起https請求,建立連接,發送所支持的ssl/tls的版本,支持的加密套件等。
- 服務器收到請求後,會發送服務端的證書,選擇的ssl/tls的版本,使用的加密套件。
- 客戶端收到證書之後對證書進行驗證,驗證證書是否被篡改,驗證證書的有效期。獲取服務器的公鑰。
- 使用服務器的公鑰對一個隨機數進行加密,傳送給服務器。
- 然後使用這個隨機數進行對稱加密進行傳輸數據。
9. 加密相關
- 對稱加密:加解密使用同一套秘鑰,常用的加密算法: AES、 DES。
- 非對稱加密:指的是加解密使用不同的密匙,一個公鑰一個私鑰。公鑰加密的信息只有私鑰能解開,私鑰加密的信息只有公鑰能解開。
- 摘要:一段信息,經過摘要算法得到一串hash值。常用的摘要算法:MD5、SHA1、SHA256。
- 數字簽名:先用摘要算法,獲取內容的摘要,之後使用自己的私鑰對摘要進行加密生成簽名。
- 數字證書:證書有簽發者、證書用途、公鑰、加密算法、hash算法、到期時間等。數字證書會做一個數字簽名防止證書被篡改。會用CA的私鑰進行加密。CA的公鑰是公開的,瀏覽器會緩存。
三. 其他
1. 自定義註解
- @target:說明了Annotation所修飾的對象範圍: constructor、method、field、package、type等等。
- @retention:定義了該Annotation被保留的時間長短, source(源文件保留)、class( class保留)、runtime(運行時有效)。
- @inherited:某個被標記的類型是被繼承的。一個類標記了帶有@inherited的註解,那麼他的子類也擁有這個註解。
- @document:被修飾的註解會生成到javadoc中。
2. 內部類
- 內部類分為:成員內部類,匿名內部類,靜態內部類,局部內部類。
- 除了靜態內部類,其他的內部類不能擁有靜態變量或靜態方法,因為內部類屬於外部類的一個成員變量,先加載外部類在加載內部類。
原因:
- 靜態變量在類加載的時候需要將符號引用替換為直接引用而此時還沒有內部類的對象。
- 內部類無法在沒有外部類的實例下直接使用。
2.1 為什麼靜態內部類可以擁有靜態常量
因為靜態常量是在編譯時期就確定的值,會存入類的常量池,而訪問常量池中的常量是不需要加載類的。
2.2 內部類的使用場景
- 達到一個多重繼承的效果
- 訪問控制,只能通過外部類調用
3. 自動拆箱裝箱
- 基本類型和引用類型之間的轉換。
- 集合類只接受對象。
- 注意包裝類的緩存值,Float和Double值沒有緩存值,Integer和Long緩存值為-128~127超過之後會自動轉換成對象。兩個包裝類型進行比較時需要用equals。
4. String為什麼是final,StringBuilder與StringBuffer的區別
- String定義成final類型表示不能被繼承,確保不會在子類中改變語義。
每次對string對象的改變相當於重新生成了一個新的string對象。經常改變的字符串不建議使用String。
- StringBuffer是線程安全的, StringBuilder是非線程安全的。
5. transient
- 被標記的成員變量不參與序列化過程。
- 只能修飾成員變量,不能修飾類和方法。
6. 如何進行序列化
- 實現Serializable接口。
- 序列化使用輸出流進行writeObject。
- 反序列化使用輸入流進行readObject。
7. 如何實現對象克隆
- 實現Cloneable接口,並重寫clone方法。
- 也可通過序列化方式進行深拷貝
- 一般實際使用過程中我們只需要拷貝對象的屬性,通常使用BeanUtils.copy()
這種拷貝都是淺拷貝
- 幾種拷貝對象的性能
cglib>Spring>apache, 一般不建議使用apache的因為對象轉換會出錯,Spring的date類型轉換也可能會出錯。
8. 異常
8.1 Error
系統級別的錯誤,程序不必處理。出了錯誤之後只能退出運行。
8.2 Exception
- 需要進行捕捉或者程序處理的異常。
- Exception分為運行時異常和受檢異常
RuntimeException包括:空指針異常,數組下標越界,classNotFound,類型轉換異常等等。
受檢異常指:編譯器要求方法必須聲明拋出可能發生的受檢異常。
9. Object中的finalize方法
如果類中重寫了finalize方法,當該類對象被回收時,finalize方法有可能會被觸發。
Java讀者福利:JavaBAT大廠面試真題+進階架構師學習視頻+編程書籍+對標年薪50W架構師進階路線路都已收集好!需要的朋友幫忙轉發一下,然後私信我【888】即可免費領取!
閱讀更多 Java肖先生 的文章