new Integer
的時候,如果整型字面量的值在-128 ~ 127之間,那麼不會new
新的Integer
對象,而是直接引用常量池中的Integer
.
Integer f1 = 100,f2 = 100,f3 = 150,f4 = 150;
f1 == f2
f3 == f4
- 通常我們定義的一個基本數據類型的”變量”,一個對象的引用,還有就是函數調用的現場保存都使用JVM中的棧空間;而通過new關鍵字的對象則放在堆空間,堆是gc的主要區域。方法區和堆是各個線程共享的內存區域。棧空間用光了,會引發
StackOverFlowError
,而堆和常量池空間不足則不會引發。
switch
在java 5之前,只能是byte,short,char,int
5引入了枚舉,7引入了String
,現在還是不支持long
- 重載是編譯時的多態性,重寫是運行時的多態性,重寫的子類方法要求和父類有相同的返回類型,比父類更好的訪問,不能比父類拋出更多的異常
- 接口比抽象類更加抽象,因爲抽象類中可以定義構造器,接口不行
- 靜態內部類可以有靜態成員,而非靜態內部類不行
- 靜態內部類只能訪問外部類的靜態成員,非靜態可以訪問所有
- 靜態內部類實例化方法:
new OuterClass.InnerClass()
,非靜態內部類實例化方法:new OuterClass().new InnerClass()
- 調用內部靜態類的方法:
OuterClass.InnerClass.method(property)
- 實現克隆的兩個方法:
- 實現
Cloneable
接口並重寫Object類中的clone()
方法;
- 實現
Serializable
接口,通過序列化實現克隆;
- 調用
ByteArrayInputStream
或者ByteArrayOutputStream
對象的close
方法沒有任何意義,這兩個基於內存的流,Gc會自動清理,不像外部資源(文件流);
- 接口可以繼承接口,抽象類可以實現接口,抽象類繼承具體類,也可以繼承抽象類;
- 字符串反轉
public static String reverse(String str){
if(str == null || str.length<=1)
return str;
return reverse(str.substring(1))+str.charAt(0);
}
finally
是在return
之前執行,也就是說就算在try
中return
了,也必須等finally
執行完成之後纔會返回。
List,Set
是繼承自Collection
接口,而Map
不是。
ArrayList
和LinkedList
都是非線程安全的,可以通過工具類Collections.synchronizedList
方法將其轉換成線程安全的。
Set
和Map
容器都有基於哈希存儲和排序樹兩種實現版本;
TreeSet
要求元素必須實現Comparable
接口,TreeMap
的鍵必須實現Comparable
接口,從而進行排序
sleep()
方法是Thread
的靜態方法,將cpu
讓出去,但是對象的鎖依然保持,因此休眠時間結束後,會自動到就緒狀態,wait
會把對象鎖也放棄,進入到對象的”等待池”中,只有調用對象的notify
才能喚醒等待池中的線程進入“等鎖池”;調用wait
方法的前提是擁有此對象的鎖,所以調用此方法必須在同步塊或同步方法中。
ExecutorService(線程池對象)
提供兩個方法來拒絕傳入新任務,shutdown
會允許以前提交的任務執行完成再終止;shutdownNow
會阻止等待任務執行,並試圖停止正在執行的任務。
- 多線程的第三種實現方式:java 5 以後,實現
callable
接口,該接口中的call方法可以在線程執行結束時產生一個返回值。
ClassName[] aa = new ClassName[11]
不會觸發類的初始化,也就是下面是不會打印出const
的。
public class ConstClass{
static{
System.out.println("const");
}
public static final int value = 123;
}
public class Main{
public static void main(String[] args){
System.out.println(ConstClass.value)
}
}
- 上面第二種調用也不會打印
const
,因爲在編譯的時候已經把age
放在常量池中了,如果把final
去掉之後就會初始化。
- 類加載機制:
- (1)加載:將
class
文件字節碼內容加載到內存中,並將這些靜態數據轉換成方法區中的運行時結構數據,在堆中生成一個代表這個類的class
對象,作爲方法區類數據的訪問入口
- (2)鏈接:將
java
類的二進制代碼合併到jvm的運行狀態之中的過程。
- (3)驗證:確保加載的類信息符合jvm規範,沒有安全方面問題。
- (4)準備:正式爲類變量(static)分配內存並設置初始值,都在方法區中進行分配。
- (5)解析:虛擬機常量池內的符號引用(還不知道目標的真正地址,只能先用一個唯一的符號代替了一下,比如類引用了另一個類,開始時是不知道另一個類的class的地址的)替換爲直接引用的過程
- (6)初始化:初始化階段是執行”類構造器方法”的過程。類構造器方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊中的語句合併產生的。
- a:當初始化 一個類的時候,如果發現其父類還沒有進行過初始化,則需要先初始化其父類的初始化
- b:虛擬機會保證一個“類的構造器方法”在多線程環境中被正確加鎖和同步
- c:當訪問一個
java
類的靜態域時,只有真正聲明這個靜態變量的類纔會被初始化。