目錄
字符串常量池
如果是創建對象還會==嗎?
Integer也是在字串常量池中復用?
字符串拼接
為什么String是不可變的?
String的不可變性是怎么做的?
外部代碼不能創建對象?
構造方法不是私有的嗎? 怎么new出來的?
那這兩個方法的各自作用呢?
為什么局部變量有初始值而成員變量沒有初始值呢?
靜態方法為什么不能調用非靜態成員?
Static 、final 、 static? final
泛型和泛型擦除
字符串常量池
字符串常量池在JDK7之前字符串常量池在運行時常量池(方法區),JDK7之后字符串常量池移動到堆中,字符串常量池的作用是在定義一個字符串的值時候會在字符串常量池中創建對象用于復用。
String a = "a";
String b = "a";
//a == b 是true
如果是創建對象還會==嗎?
答案是不會的。
String a = new String("a");
String b = "a";
// a == b 為false
因為new 一個字符串相當于在堆中和常量池都創建對象,所以是不相等的。
Integer也是在字串常量池中復用?
不是的,Integer是單獨的緩存機制,緩存范圍是-128~127之間。
Integer a = 127;
Integer b = 127;
//a==b 是true
Integer a = 129;
Integer b = 129;
//a==b 是false
字符串拼接
字符串拼接分成 變量拼接和常量拼接
String a = "a";
String b = "b";
String c = "a"+"b";//這樣是常量拼接,編譯器會把這個編譯成String c = "ab";
String d = a+b;//這個是變量拼接,相當于StringBuilder d = new StringBuilder().addpend("a").addend("b");但是不會放在字符串常量池中,字符串常量池中只有"a"和"b",然后堆中有 ab 和 StringBuilder對象
為什么String是不可變的?
首先是因為安全性,因為String如果是可變的在多線程的環境中不斷修改會造成未知的錯誤。其次是不可變性可以是String擁有緩存機制,再其次就是String的不可變性和StringBuilder、StringBuffer的可變性形成互補。
String的不可變性是怎么做的?
首先是因為String的底層是一個char[] 然后他是被final和 private 修飾的,這就導致了String一旦初始化就不能被修改或者重新賦值。其次是String內部的構造方法是私有的,這會導致外部代碼不能直接創建String對象。
外部代碼不能創建對象?
對的,String a = "a";是通過字符串常量池創建的,String a = new String("a");是通過構造方法創建的。
構造方法不是私有的嗎? 怎么new出來的?
new的這個不是通過那個private的構造方法創建的,其實在String內部是有公開的構造方法的,
public String(String original) {this.value = original.value;
}
//
private String(char value[]) {this.value = value;
}
那這兩個方法的各自作用呢?
首先公開的那個方法主要是接收字符串的值,然后在內部調用哪個私有的方法去創建對象,完成對象的初始化。
為什么局部變量有初始值而成員變量沒有初始值呢?
首先我們要清楚局部變量是在一個代碼塊里面,所以我們必須要給他賦值,因為,局部變量的生命周期是很短的,其實作用域范圍也很小,編譯器無法確定局部變量的初始值,所以必須要賦值。
成員變量的生命周期長、作用域很大,很可能在某一個方法某一個階段賦值,即使我們沒有給成員變量賦值系統也會自動給成員變量賦初值。
靜態方法為什么不能調用非靜態成員?
ps:類加載:加載 - 驗證 -??準備 - 解析 - 初始化
這個要和類加載有關了,靜態方法的初始化是在類加載的時候初始化的,而非靜態成員是在new 出來的他們的時候創建的,你用存在的去調用一個當前不存在的,這是不合理的!
Static 、final 、 static? final
static 表示讓這個方法和變量屬于這個類,而不是屬于實例對象
final 可以修飾類、方法、變量,表示類不能被繼承、方法不能被重寫、變量的值不能變
static final?表示變量屬于類本身且一旦初始化后不能被改變。
泛型和泛型擦除
泛型(Generics)是一種類型安全的機制,它允許你在定義類、接口和方法時使用類型參數。泛型的主要優點是類型安全和代碼的重用性。然而,Java的泛型實現有一個重要的特性叫做“泛型擦除”(Type Erasure),這是為了保持向后兼容性而設計的。
在編譯時,類型參數被替換為Object
,類型信息在運行時被擦除。