Java中String類是java.lang包下的一個類,它被final關鍵字修飾。final關鍵字可以修飾類、變量和方法。被final修飾有如下特性:
①final修飾類,表示該類不能被繼承。類不能被繼承,標誌着該類的屬性和方法不能被其他類繼承;
②final可以修飾靜態成員變量(也叫類變量)、普通成員變量、局部變量。
被final修飾的變量稱作final變量,也叫做final常量。一般來說,final常量名大寫。
而值得注意的是,final修飾類變量的時候,必須在聲明的時候就要顯式地賦值,並且一旦賦值就不能再更改!
final修飾普通成員變量時,要麼在聲明的時候顯式地賦值,要麼在構造方法中賦值(如果該類有多個構造方法,那麼每一個構造方法中都要顯式地賦值或者調用this()方法),並且一旦賦值就不能改變!
final修飾局部變量的時候,不必第一次就賦值,而是可以再用到的時候再賦值。但是一旦賦值,就不能再更改!
final常量和final變量是隻讀的,不能再修改他們的值。
final修飾引用變量時,變量的引用不能改,但是可以改變引用的內容!這個需要注意!
③final修飾方法,代表這個方法不可以被子類重寫。final方法比非final方法要快,因爲在編譯的時候已經靜態綁定了,不需要在運行時再動態綁定了。
以上是final關鍵字的作用。
通過對String源碼進行查看,發現String類是被final修飾的,說明String不能被繼承,它的屬性和方法都不能通過繼承管理被複用。同時,String的成員變量有兩個,一個是被final修飾的字符數組char[] value,一個是普通屬性散列碼hash。
其中,value是字符數組常量,在構造方法時就被賦值了。在其他的方法中,都沒有去修改這個value的值,事實上,修改的話是不能編譯通過的,因爲final常量是隻讀的。
關於String的一些特性,經常會在面試過程中被問到。
========================面試問題分割線========================
String是一個特殊的包裝類數據,可以用:
String str = new String("abc");
String str = "abc";
兩種形式來創建,第一種是用new()來創建對象的,它會存放在堆中,每調用一次就會創建一個新的對象;而第二種是先在棧中創建一個對String類的對象引用變量str ,然後查找字符串常量池中有沒有存放"abc",如果沒有,則將"abc"存放到字符串常量池中,並令str 指向"abc",如果已經有"abc",則直接令str 指向"abc"。
面試官也會問,第一種方式創建了幾個對象?
首先是在堆內存中生成了一個對象,值爲“abc”,同時會去常量池中查找是否存在這個字符串,如果不存在則生成一個"abc"放到池子裏去,因此可以說是創建了兩個對象。
比較類裏面的數值是否相等時,用equals()方法;當測試兩個包裝類的引用是否指向同一個對象時,用 == ,下面用例子說明上面的理論。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2); // true
可以看出str1 和str2 指向同一個對象
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2); // false
用new的方式是生成不同的對象,每一次調用都生成一個新的對象。
因此用第二種方式(String str = "abc";)創建多個"abc"字符串,在內存中其實只存放一個對象而已。這種寫法有利於節省內存空間,同時它可以在一定程度上提高程序的運行速度,因爲jvm(java virtual machine)會自動根據棧中數據的實際情況來決定是否有必要創建新的對象。而對於String str = new String("abc"); 的代碼,則一概在堆中創建新對象,而不管其字符串值是否相等,是否有必要創建新的對象,從而加重了程序的負擔。
另一方面,要注意:
我們在使用諸如String str = "abc";的格式創建對象時,總是想當然地認爲創建了String類的對象str,小心陷阱,對象可能並沒有被創建!而可能只是指向一個先前已經創建好的對象。只有通過new()方法才能保證每次都創建一個新的對象。由於String類的不可變(immutable)性質,當String變量需要經常變換其值時,應該考慮使用StringBuffer類,以提高程序效率。
例子:
String a = "abc";
String b = "abc";
String c = new String("abc");
String d = c.intern();
這段代碼(code)共創建了幾個對象?
我認爲是兩個,首先a,b指向池子裏的同一個字符串"abc",c指向堆裏面的對象,d指向常量池中的"abc",因此我認爲是創建了兩個對象。
說完了String,那麼另一個值得關注的類是Integer,看下面的例子:
int a=1;
Integer b=1;
Integer c=new Integer(1);
Integer d=new Integer(1);
Integer e=223;
Integer f=223;
思考:
a==b true or false?
a==c true or false?
b==c true or false?
c==d true or false?
e==f true or false?
想知道答案及原因?且聽下回分解!