final修飾的變量引用不能變還是對象不可變
兩種情況:如果是基本數據類型,被final修飾的變量一旦初始化就不能改變;如果是引用數據類型的變量,初始化之後不能只想另外一個對象。
基本數據類型:
package cn.yqg.day2; public class StringTest { public static void main(String[] args) { final int a; int b=234; a=b; System.out.println(a); } }
我們看到上面的代碼a是final類型的,但是沒有被初始化,所以可以給a賦值。如果a被初始化,a存儲的值就不能改變了,示例如下。
package cn.yqg.day2; public class StringTest { public static void main(String[] args) { final int a=123; int b=234; a=b;//編譯通不過,會報錯建議去掉fianl System.out.println(a); } }
如果是引用數據類型
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
package cn.yqg.day2; public class StringTest { public static void main(String[] args) { final StringBuffer a=new StringBuffer("ppp"); System.out.println(a); System.out.println(a.hashCode()); a.append("kkk"); System.out.println(a); System.out.println(a.hashCode()); } }
運行結果:
ppp 2018699554 pppkkk 2018699554
我們發現變量內容變了,引用沒變。
我們把String定義為final類型,那麽String類不能被繼承,引用不能被改變,但是引用地址指向的內存的地址存儲的對象是可以改變的
String a="ppp"; a=a+"kkk";
我們看到a的對象內容改變了
不允許String類的引用被改變是為了安全性著想,我們看這個例子。
package cn.yqg.day3; public class Test2 { public static void main(String[] args) { String a=new String("fds"); String b=new String("ddd"); String c=b; c=c+"ds"; System.out.println(b); System.out.println(c); } }
運行內存圖:
運行結果:
ddd
dddds
我們從此可以知道,上面的String c=b;並不是將b的地址復制給c,而是c新開辟一個地址並進行存貯,這就保證了String類的安全性,相反StringBuilder就存在安全隱患
package cn.yqg.day3; public class Test2 { public static void main(String[] args) { StringBuilder s=new StringBuilder("ppp"); StringBuilder r=s; r.append("kkk"); System.out.println(r); System.out.println(s); } }
運行結果:
pppkkk
pppkkk
r改變會導致s也改變,因為他們指向得內存地址一樣。
------------------------------------------------------------------------------------------------------------------------------------------------------
final修飾的變量引用不能變還是對象不可變