String是一個很是經常使用的類,應該深刻的去了解Stringjava
如:spa
String str =new String("abc")指針
String str1 = "abc"code
System.out.println(str == str1)對象
System.out.println(str.equal(str1))blog
結果:內存
false字符串
trueget
緣由解析:編譯器
1. 執行語句String str="abc";時。首先查看字符串池中是否存在字符串"abc",若是存在則直接將「abc」賦給str,若是不存在則先在 字 符串池中新建一個字符串"abc",而後再將其賦給str.
2. 執行語句String str = new String("abc");時。無論字符串池中是否存在字符串「abc」,直接新建一個字符串「abc」,(注意,新建的字符串「abc」不是在字符串池中), 而後將其賦給str。因而可知 1.的效率要高於2的效率。
3. String str1="java";//指向字符串池
String str2="blog";//指向字符串池
String s = str1+str2;
+運算符會在堆中創建起兩個String對象,這兩個對象的值分別是「java」,"blog",也就是說從字符串常量池中複製這兩個值,而後再堆中建立兩個對象。而後再創建對象s,而後將「javablog」的堆地址賦給s. 這句話共建立了3個String對象。
System.out.println(s=="javablog");//結果是false;
JVM確實對形如String str="javablog";的對象放在常量池中,可是它是在編譯時name作的。而String s=str1+str2;是在運行時候才能知道的,也就是說str1+str2是在堆裏建立的,因此結果爲false了。
String s="java"+"blog";//直接將javablog對象放入字符串池中。 System.out.println(s=="javablog");//結果是true;
String s=str1+"blog";//不放在字符串池中,而是在堆中分分配。 System.out.println(s=="javablog");//結果是false;
總之,建立字符串有兩種方式:兩種內存區域(pool,heap)
1.""建立的字符串在字符串池中。
2.new 建立字符串時,首先查看池中是否有相同的字符串,若是有則拷貝一份放到堆中,而後返回堆中的地址;若是池中沒有則在堆中建立一分,而後返回堆中的地址,
3.在對字符串賦值時,若是右操做數含有一個或一個以上的字符串引用時,則在堆中再創建一個字符串對象,返回引用如:String s= str1+"blog";
之間的區別
第1種:
String a="abc";
String b="abc";
System.out.print(a==b);
結果:true
緣由:編譯時,這兩個"abc"被認爲是同一個對象保存到了常量池中;運行時JVM則認爲這兩個變量賦的是同一個對象,因此返回true。
---------------------
第2種:
String a=new String("abc");
String b=new String("abc");
System.out.print(a==b);
結果:false
緣由:用構造器建立的對象,是不會被放入常理池中的,也很明顯這徹底是兩個對象,只是內容相同罷了,結果固然爲false了。用equals()或者System.out.print(a.intern()==b.intern());就返回true了。
------------------------------
第3種
String a="abc";
String b=new String("abc");
System.out.print(a==b);
結果:false
緣由:同上。此外,a
---------------------------
第4種
String a="abcdef";
System.out.print(a=="abcdef");
結果:true
緣由:運行出現的字符串常量,如果在常量池中出現過,則JVM會認爲同一個對象,以節省內存開銷,因此這兩個字符串會被認爲是同一個對象。
-------------------------------------------
第5種
String a="abcdef";
String b="";
String c=a+b;
System.out.print(c=="abcdef");
結果:false
緣由:編譯時,先將"abcedf"放在常量池中,而c的值則是在運行時在堆裏建立的。因此爲false。的類加載時就完成了初始化,而b要在執行引擎執行到那一行代碼時才完成初始化。
具體差異以下:
class Test {
public static void main(String[] args) {
Object o1;
o1.toString(); /*這裏編譯不能經過,編譯器只認定o1是個引用,沒指向任何對象,因此不能調用方法。*/
Object o2 = null;
o2.toString(); /*這裏編譯能夠過,可是有空指針異常,編譯器認定o2是一個對象,雖然是一個空對象。*/
}
}
null對象是一個特殊的對象,他能夠是任何類型。他只是做爲一個標記而已,只是爲了標記不存在而存在的。也不必去追究他在內存是什麼樣。null就是一個標記而已。容器能夠接受一個空對象,可是一個空引用則是不接受的。
Object o; //這種寫法只是分配一個引用,沒有分配內存。
Object o = null; //這麼寫則是給引用指向了一個空對象。分配了內存(空對象),因此編譯不會報錯,運行時報空指針異常。