Java中字串定義,初始化,賦值為null的區別
1、概述:
字串定義 只定義不分配記憶體空間,不做任何操作;
字串初始化 兩種方式直接等號賦值,用new初始化,直接等號賦值放入記憶體池,其它變數也可以引用;new初始化分配記憶體空間,不可引用;字串賦值為null 初始化了,並且有了引用,但是沒有指向任何記憶體空間;
2、詳解:
String s;和String s=null;和String s="a";有什麼區別?
第一個只是定義了一個String型別變數s,並沒有給它賦初值,在Java中,預設在使用一個變數的時候必須賦予它初值(降低風險)。
第二個和第三個都定義了String型別變數s,並賦予它初值,只不過第二個賦予的值為null(空)罷了
主要要理解的是
String s; s為一個引用~~它不是物件
第一個是沒有初始化的引用;
第二個為空引用;
第三個是在字串池裡寫入一個字元'a',然後用s指向它。
String s;只是給s分配一個記憶體空間
String s=null;是分配的空間中儲存的值為空值
String s="a";這句就不用我多說了分配的空間的值為字元a
特別關注:String s="a"和String s=new String("a");是有本質上的區別的
前者是在字串池裡寫入一個字元'a',然後用s指向它;
後者是在堆上建立一個內容為"a"的字串物件。
1、雙引號的方式
String x = abcd;
String y = abcd;
System.out.println(x==y);//true
System.out.println(x.equals(y));//true
上面的輸出結果:
x==y 的結果為true 是因為通過雙引號賦值的方式之後,x 和 y 都是指向同一個記憶體地址,他們的引用都是指向方法區中的同一個內容,引用地址是一樣的, 當同一個String字面值無論被建立多少次,始終只有一個記憶體地址被分配,之後的都是這個String的拷貝,Java中稱作“字串駐留”,所有的字串常量在編譯之後都會自動的駐留。x = abcd這種方式建立的時候首先會檢視字串池中是否已經存在,存在就直接返回PermGen中的該String物件,否則就會建立一個新的String物件,之後再放進字串池中。
JVM裡,考慮到垃圾回收(Garbage Collection)的方便,將 heap 劃分為三部分: young generation (新生代)、 tenured generation(old generation)(舊生代)和 permanent generation( permgen )(永久代)
字串池是為了解決字串重複的問題,生命週期長,它存在於 permgen 中。
編譯 Java 原始碼時,原始檔中出現的雙引號內的字串都被收納到常量池中,用 CONSTANT_utf8_info 項儲存著。
JVM 中,相應的類被載入執行後,常量池對應的對映到 JVM 的執行時常量池中。其中每項 CONSTANT_utf8_info(也就試記錄那些字串的)都會在常量引用解析時,自動生成相應的 internal String,記錄在字串池中。
2、構造器的方式
String a = new String(abcd);
String b = new String(abcd);
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
上面程式碼執行結果:
a==b 為false 是因為通過new 構造器的方法建立之後,在heap堆中分別分配了兩個記憶體地址。a 和 b 分別指向了堆中的兩個不同的物件,不同的物件就會有不同的地址分配。
下面這張圖就很好的闡述了上面的兩種情況:
關注微信公眾號和今日頭條,精彩文章持續更新中。。。。。