Java中String類探討

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?

 

想知道答案及原因?且聽下回分解!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章