一. Java基礎(chǔ)
- 在java中String類為什么要設(shè)計成final?
- ClassLoader.loadClass()與Class.forName()的區(qū)別
- String 編碼UTF-8 和GBK的區(qū)別?
字符編碼筆記:ASCII,Unicode和UTF-8 。
(精)字符集GBK和UTF8的區(qū)別說明 - 什么時候使用字節(jié)流、什么時候使用字符流,二者的區(qū)別
JVM
1、JVM初始化步驟 ? 2、類初始化時機(jī) ?3、哪幾種情況下,Java虛擬機(jī)將結(jié)束生命周期?
初始化,為類的靜態(tài)變量賦予正確的初始值,JVM負(fù)責(zé)對類進(jìn)行初始化,主要對類變量進(jìn)行初始化。在Java中對類變量進(jìn)行初始值設(shè)定有兩種方式:
①聲明類變量是指定初始值
②使用靜態(tài)代碼塊為類變量指定初始值
- JVM初始化步驟
1、假如這個類還沒有被加載和連接,則程序先加載并連接該類
2、假如該類的直接父類還沒有被初始化,則先初始化其直接父類
3、假如類中有初始化語句,則系統(tǒng)依次執(zhí)行這些初始化語句 - 類初始化時機(jī):只有當(dāng)對類的主動使用的時候才會導(dǎo)致類的初始化,類的主動使用包括以下六種:
- 創(chuàng)建類的實(shí)例,也就是new的方式
- 訪問某個類或接口的靜態(tài)變量,或者對該靜態(tài)變量賦值
- 調(diào)用類的靜態(tài)方法
- 反射(如Class.forName(“com.shengsiyuan.Test”))
- 初始化某個類的子類,則其父類也會被初始化
- Java虛擬機(jī)啟動時被標(biāo)明為啟動類的類(Java Test),直接使用java.exe命令來運(yùn)行某個主類
- 結(jié)束生命周期
在如下幾種情況下,Java虛擬機(jī)將結(jié)束生命周期- 執(zhí)行了System.exit()方法
- 程序正常執(zhí)行結(jié)束
- 程序在執(zhí)行過程中遇到了異常或錯誤而異常終止
- 由于操作系統(tǒng)出現(xiàn)錯誤而導(dǎo)致Java虛擬機(jī)進(jìn)程終止
Java 并發(fā)
如何合理的配置java線程池?如CPU密集型的任務(wù),基本線程池應(yīng)該配置多大?IO密集型的任務(wù),基本線程池應(yīng)該配置多大?用有界隊列好還是無界隊列好?任務(wù)非常多的時候,使用什么阻塞隊列能獲取最好的吞吐量?
答:1)配置線程池時CPU密集型任務(wù)可以少配置線程數(shù),大概和機(jī)器的cpu核數(shù)相當(dāng),可以使得每個線程都在執(zhí)行任務(wù)
2)IO密集型時,大部分線程都阻塞,故需要多配置線程數(shù),2*cpu核數(shù)
3)有界隊列和無界隊列的配置需區(qū)分業(yè)務(wù)場景,一般情況下配置有界隊列,在一些可能會有爆發(fā)性增長的情況下使用無界隊列。
4)任務(wù)非常多時,使用非阻塞隊列使用CAS操作替代鎖可以獲得好的吞吐量。
動態(tài)代理
在程序運(yùn)行時,運(yùn)用反射機(jī)制動態(tài)創(chuàng)建而成。動態(tài)代理的優(yōu)勢就是實(shí)現(xiàn)無侵入式的代碼擴(kuò)展。
應(yīng)用場景
- 方法增強(qiáng),Spring AOP
- 遠(yuǎn)程調(diào)用,RPC
JDK動態(tài)代理與CGLIB區(qū)別
- JDK動態(tài)代理只能對實(shí)現(xiàn)了接口的類生成代理,而不能針對類。
- CGLIB是針對類實(shí)現(xiàn)代理,主要是對指定的類生成一個子類,覆蓋其中的方法。
CGLIB是一個強(qiáng)大的高性能的代碼生成庫。作為JDK動態(tài)代理的互補(bǔ),它對于那些沒有實(shí)現(xiàn)接口的類提供了代理方案。在底層,它使用ASM字節(jié)碼操縱框架。本質(zhì)上來說,CGLIB通過產(chǎn)生子類覆蓋非final方法來進(jìn)行代理。它比使用Java反射的JDK動態(tài)代理方法更快。CGLIB不能代理一個final類或者final方法。通常來說,你可以使用JDK動態(tài)代理方法來創(chuàng)建代理,對于沒有接口的情況或者性能因素,CGLIB是一個很好的選擇。