一、String篇
1、String基本介紹?
(jdk文件原文)String
類代表字串。 Java程式中的所有字串文字(例如"abc"
)都被實現為此類的例項。
說人話就是:String是用來儲存字串的,比如:“我好帥啊”、“123456”、"hello"這些都是字串,而區分是否為字串的標誌就是這對雙引號:""。
2、String類特性:
-
String是一個final類,代表不可變的字元序列。
-
字串是常量,用雙引號引起來表示。它們的值在建立之後不能更改。
-
String物件的字元內容是儲存在一個字元陣列value[]中的。
字串不變; 它們的值在建立後不能被更改。 字串緩衝區支援可變字串。 因為String物件是不可變的,它們可以被共享。 例如:
String str = "abc";
相當於:
char data[] = {'a', 'b', 'c'}; String str = new String(data);
以下是一些如何使用字串的示例:
System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2,3); String d = cde.substring(1, 2);
3、為什麼String是不可變的?
我們看看原始碼,發現value這個字元陣列被final修飾了,怪不得String是不可變的。
4、String的繼承圖以及父類介紹
1)Serializable:
-
public interface Serializable
類的序列化由實現java.io.Serializable介面的類啟用。不實現此介面的類將不會使任何狀態序列化或反序列化。可序列化類的所有子型別都是可序列化的。序列化介面沒有方法或欄位,僅用於標識可序列化的語義。
為了允許序列化不可序列化的子型別,子型別可能承擔儲存和恢復超型別的公共,受保護和(如果可訪問)包欄位的狀態的責任。 子型別可以承擔此責任,只有當它擴充套件的類具有可訪問的無引數建構函式來初始化類的狀態。 如果不是這樣,宣告一個類Serializable是一個錯誤。 錯誤將在執行時檢測到。
在反序列化期間,非可序列化類的欄位將使用該類的public或protected no-arg建構函式進行初始化。 對於可序列化的子類,必須可以訪問no-arg建構函式。 可序列化子類的欄位將從流中恢復。
當遍歷圖形時,可能會遇到不支援Serializable介面的物件。 在這種情況下,將丟擲NotSerializableException,並將標識不可序列化物件的類
2)Comparable<T>:
-
public interface Comparable<T>
該介面對實現它的每個類的物件強加一個整體排序。這個排序被稱為類的自然排序 ,類的
compareTo
方法被稱為其自然比較方法 。Collections.sort
(和Arrays.sort
)可以自動對實現此介面的物件進行列表(和陣列)排序。 實現該介面的物件,可以使用如在鍵sorted map或作為在元件sorted set ,而不需要指定一個comparator 。一類
C
的自然順序被說成是與equals一致當且僅當e1.compareTo(e2) == 0
對每一個e1
和C
類e2
相同的布林值e1.equals(e2)。
請注意,null
不是任何類的例項,e.compareTo(null)
應該丟擲一個NullPointerException
即使e.equals(null)
返回false
。強烈建議(儘管不需要)自然排序與等於一致。 這是因為,當沒有顯式比較器的排序集(和排序對映)與其自然排序與equals不一致的元素(或鍵)一起使用時會“奇怪地”。 特別地,這種排序集合(或排序對映)違反了根據
equals
方法定義的集合(或對映)的一般合同。
3)CharSequence:
-
public interface CharSequence
CharSequence
是char
值的可讀序列。該介面提供統一的,只讀訪問許多不同型別的char
序列。char
值代表基本多語言平面(BMP)或代理中的一個字元。詳見Unicode Character Representation 。此介面不會完善
equals
和hashCode
方法的一般合同。 因此,比較兩個物件實現CharSequence
其結果是,在一般情況下,不確定的。 每個物件可以由不同的類實現,並且不能保證每個類都能夠測試其例項以與另一個類相同。 因此,使用任意的CharSequence
例項作為集合中的元素或對映中的鍵是不合適的
5、建立 String 物件的兩種方式
方式一、直接賦值:String s = "歸海";
這種方式它首先會先從常量池檢視是否有"歸海" 這個資料空間,如果有就直接指向,如果沒有就建立一個”歸海“這個資料空間然後指向它。注意s最終指向的是常量池的空間地址。
方式二、呼叫構造器 String s1= new String("歸海");
這種方式則是先在堆中建立空間,裡面維護了value屬性,指向常量池的"歸海"空間。如果常量池中沒有''歸海'',則重新建立,如果有就直接通過value指向。注意這裡最終指向的是堆中的空間地址。
經過剛才簡單的介紹你應該對String有一點印象了,ok話不多說來幾道練習題:
例題一:
String a = "abc';
String b = "abc'';
System.out.println(a == b) ; //true/fales
System.out.println(a.equals(b));//true/fales
例題二:
String a = new String("abc");
String b = new String("abc");
System.out.println(a == b) ; //true/fales
System.out.println(a.equals(b));//true/fales
例題三:
String a = "歸海';
String b = new String("歸海");
System.out.println(a == b) ; //true/fales
System.out.println(a.equals(b));//true/fales
例題四:
Person p1 = new Person();
p1.name = "歸海";
Person p2 = new Person() ;
p2.name = "歸海";
System.out.println(p1.name.equals(p2.name));//true/fales
System.out.println(p1.name == p2.name) ; //true/fales
System.out.println(p1.name == "歸海") ; //true/fales
來說一下答案吧。
(1)T, T;
(2)F, T;
(3)F, T;
(4)T, T, T;
6、String 類常用方法
下面是 String 類支援的方法,更多詳細內容,參看
序號 | 方法描述 |
---|---|
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | [static String copyValueOf(char |
8 | [static String copyValueOf(char |
9 | |
10 | |
11 | |
12 | [byte |
13 | [byte |
14 | [void getChars(int srcBegin, int srcEnd, char |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | [String |
33 | [String |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | [char |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 |
不過發現沒String類的效率有點低啊!這是String類因為每次更新內容都要重新開闢空間,為此java設計者還提供了StringBuilder和SreingBuffer類來增強String功能和效率。
二、StringBuffer篇
1、StringBuffer基本介紹?
1)它也是一個元老級別的類了從jdk1.0的時候就有了
2)StringBuffer是一個可變的字元序列,可以對字元內容進行更改。
3)StringBuffer的很多方法也String相同,但是StringBuffer是可變長度的。
4)StringBuffer是一個容器。
2、StringBuffer的特性:
1)執行緒安全,可變的字元序列。 字串緩衝區就像一個String
,但可以修改。
2)字元緩衝可以安全的被多個執行緒使用。前提是這些方法必須進行同步。
3)每個字串緩衝區都有一個容量。 只要字串緩衝區中包含的字元序列的長度不超過容量,就不必分配新的內部緩衝區陣列。 如果內部緩衝區溢位,則會自動變大
private transient char[] toStringCache; 這是StringBuffer可以更改的原因。
3、StringBuffer注意事項:
StringBuffer類不同於String,其物件必須使用構造器生成。有三個構造器:
-
StringBuffer():初始容量為16的字串緩衝區
-
StringBuffer(int size):構造指定容量的字串緩衝區
-
StringBuffer(String str):將內容初始化為指定字串內容
4、StringBuffer的繼承圖以及父類介紹:
1)Appendable:
-
public interface Appendable
可附加
char
序列和值的物件。Appendable
介面必須由其例項旨在從Formatter
接收格式化輸出的任何類實現 。要附加的字元應為Unicode Character Representation中描述的有效Unicode字元。 請注意,補充字元可以由多個16位
char
值組成。對於多執行緒訪問,附加功能不一定是安全的。 執行緒安全是擴充套件和實現這個介面的類的責任。
由於此介面可能由具有不同樣式的錯誤處理的現有類實現,因此不能保證將錯誤傳播到呼叫者。
2)AbstractStringBuilder:首先這是一個類
位置:java.lang包中 |
---|
宣告: abstract class AbstractStringBuilderimplements Appendable, CharSequence |
AbstractStringBuilder 類有abstract 修飾,可知它不能被例項化。AbstractStringBuilder 類有兩個子類:StringBuilder和StringBuffer。 |
5、StringBuffer類常用方法:
序號 | 方法描述 |
---|---|
1 | public StringBuffer append(String s) 將指定的字串追加到此字元序列。 |
2 | public StringBuffer reverse() 將此字元序列用其反轉形式取代。 |
3 | public delete(int start, int end) 移除此序列的子字串中的字元。 |
4 | public insert(int offset, int i) 將 int 引數的字串表示形式插入此序列中。 |
5 | replace(int start, int end, String str) 使用給定 String 中的字元替換此序列的子字串中的字元 |
6、String類和StringBuffer的區別:
1)String用於字串操作,屬於不可變類,而StringBuffer也是用於字串操作,不同之處是StringBuffer屬於可變類。
2) String是不可變類,也就是說,String物件一旦被建立,其值將不能被改變,而StringBuffer是可變類,當物件被建立後,仍然可以對其值進行修改。
3)String類每次更新實際上是更改地址,因此它的效率低。
4)StringBuffer類每次更新是更新內容,不用更新地址,因此它的效率高。
三、StringBuilder篇
1、StringBuilder基本介紹:
1)一個可變的的字元序列。提供了和SteingBuffer相容的API。
2)StringBuilder是執行緒不安全的,此類設計用作簡易替換為StringBuffer
在正在使用由單個執行緒字串緩衝區的地方。
3)StringBuilder的主要StringBuilder
是append
和insert
方法,它們是過載的,以便接受任何型別的資料。 每個都有效地將給定的資料轉換為字串,然後將該字串的字元附加或插入字串構建器。
4)它的速度比StringBuffer快畢竟執行緒不安全換來的。
2、StringBuilder的繼承圖以及原始碼:
我們會發現和StringBuffer一模一樣,所以它們的API相容也是正常。
原始碼也沒什麼說的,因為我也不會。
3、String、StringBuffer、StringBuilder的區別:
對比String、StringBuffer、StringBuilder
-
String(JDK1.0):不可變字元序列 ,效率低但是複用率高。
-
StringBuffer(JDK1.0):可變字元序列、效率較高、執行緒安全。
-
StringBuilder(JDK 5.0):可變字元序列、效率最高、執行緒不安全
注意:作為引數傳遞的話,方法內部String不會改變其值,StringBuffer和StringBuilder 會改變其值。
4、String、StringBuffer、StringBuilder的效率測試
程式碼例子:
這個是 i < 180000次的結果
可以發現如果次數不是很大StringBuffer和StringBuilder的差距還是可以的。次數越大差距越大。
四、總結:
String、StringBuffer、StringBuilder的選擇:
1、如果字串中存在大量的修改操作,可以選擇StrinBuffer和StringBuilder其中之一。
2、如果字串中存在大量的修改操作而且在單執行緒的情況下,使用StringBuilder。
3、如果字串中存在大量的修改操作而且在多執行緒的情況下,使用StringBuffer。
4、如果字串修改很少、被多個物件引用,使用String。這個在配置資訊的時候應用廣泛。