天天看點

黑馬程式員_十 【String】【StringBuffer】【基本資料包裝類】

--------------------- android教育訓練、java教育訓練、java學習型技術部落格、期待與您交流! -------------------

【Sing】【StringBuffer】【StringBuilder】【基本類型包裝類】

 1  String類 

String類的定義:

public final class String  沒有子類,因為用final修飾了

String 類是描述字元串的類。Java 程式中的所有字元串字面值(如"abc")都作為此類的執行個體實作。也就是說隻要用“”雙引号引起來的,都是一個String的一個具體對象。

檢視API發現String有很多構造函數,其中就有空參數構造函數

String s =new String();

String s = “ ”;

上面兩條指令一個意思,因為第一個比較麻煩,一般都是用第二種。

String s1 = “abc”;s1是一個類類型變量,是以”abc”是一個類類型變量。

字元串的特點是一旦被初始化,就不能改變。字元串常量就是這個意思,固定不變的一個值。

如果再輸入s1 = “kk”這個時候如果輸出s1就是kk。這個時候上面的abc沒有改變,隻不過s1的位址指向了kk,上面的abc還是常量。

String s2=new  String(“abc”);

1.  s1==s2

2.  s1.equals(s2)

上面的第一個為false,第二個true,因為s2是new出來的對象,new String(“abc”)實質是建立了兩個對象,s2指向了該對象;而第二個equals判斷是記憶體中的位址值,s1和s2指向的是同一個位址。String類複寫了Object類中equals方法,該方法用于判斷字元串是否相同。

String s1 = “abc”

String s2=new  String(“abc”);

String s3 = “abc”

S1==s2   輸出結果是false

S1==s3   輸出結果是true

S1和s2的差別

S1在記憶體中有一個對象,s2在記憶體中有兩個對象。就這一個差別。S2有兩個對象是因為一個常量abc,另一個是new String,分别存在于常量池和堆記憶體中,兩個對象。

其實記憶體塊裡面有個常量池,字元串會存放在常量池裡面。

s1==s3是因為s3建立的時候,發現記憶體中已經有abc了,是以就不單獨再開空間了。是以相等。

字元串四個特點

|--字元串類型的資料是一個對象

|--是一個常量,不能被改變

|--s1和s2的差別

4|--s1.equals(s2),字元串類中覆寫了object類中的equals方法,用來判斷字元串内容是否相同

擴充知識:

“==”判斷的是兩個變量或執行個體是否是指向同一個記憶體位址;

equals是判斷兩個變量或執行個體所指向的記憶體空間的值是不是相同;

instanceof是判斷兩個變量(引用)是否是同一個類類型的。

(1)對于字元串變量來說,使用“==”和“equals()”方法比較字元串時,其比較方法不同。

“==”比較兩個變量本身的值,即兩個對象在記憶體中的首位址。

“equals()”比較字元串中所包含的内容是否相同。

比如:

String s1,s2,s3 = "abc", s4 ="abc" ;

s1 = new String("abc");

s2 = new String("abc");

那麼:

s1==s2   是 false      //兩個變量的記憶體位址不一樣,也就是說它們指向的對象不 一樣,

故不相等。

s1.equals(s2) 是 true    //兩個變量的所包含的内容是abc,故相等。

注意:

如果:        StringBuffer s1 =new StringBuffer("a");

                StringBuffer s2 = new StringBuffer("a");

結果:      s1.equals(s2)  //是false

解釋:StringBuffer類中沒有重新定義equals這個方法,是以這個方法就來自Object類, 而Object類中的equals方法是用來比較“位址”的,是以等于false.

注意:

對于s3和s4來說,有一點不一樣要引起注意,由于s3和s4是兩個字元

串常量所生成的變量,其中所存放的記憶體位址是相等的,

是以s3==s4是true(即使沒有s3=s4這樣一個指派語句)

(2)對于非字元串變量來說,"=="和"equals"方法的作用是相同的都是用來比較其

對象在堆記憶體的首位址,即用來比較兩個引用變量是否指向同一個對象。

例子:

class A

{

      A obj1   =   new  A();

      A obj2   =   new  A();

}

那麼:obj1==obj2是false

            obj1.equals(obj2)是false

但是如加上這樣一句:obj1=obj2;

那麼  obj1==obj2  是true

          obj1.equals(obj2) 是true

總之:equals方法對于字元串來說是比較内容的,而對于非字元串來說是比較

其指向的對象是否相同的。

     “==” 比較符也是比較指向的對象是否相同的也就是對象在對記憶體中的的首位址。

String類中重新定義了equals這個方法,而且比較的是值,而不是位址。是以是true。

equals方法和instanceof 的差別:

instanceof操作符用于判斷一個引用類型所引用的對象是否是一個類的執行個體 .對于引用類型變量,Java 編譯器隻根據變量被先生聲明的類去編譯。

instanceof 左邊操作元被顯式聲明的類型與右邊操作元必須是同種類或者有繼承關系,即位于繼承樹的同一個繼承分支上,否則編譯出錯.

Object 類的 equals() 方法的比較規則為:當參數 obj 引用的對象與目前對象為同一個對象時,就傳回true,否則傳回false

在JDK中有一些類覆寫了 Object 類的equals()方法,它們的比較規則為:

如果兩個對象的類型一緻,并且内容一緻,則傳回true。

這些類包括:java.io.File、java.util.Date、java.lang.String、包裝類(如java.lang.Integer和java.lang.Double類)。

如果是自己定義的類的話,可以複寫equals()方法,自己定義比較規則

Java語言對equals()的要求如下,這些要求是必須遵循的,以下幾點也算是和instanceof 的差別: 

|----對稱性:如果x.equals(y)傳回是“true”,那麼y.equals(x)也應該傳回是“true”。 

|----反射性:x.equals(x)必須傳回是“true”。 

|---- 類推性:如果x.equals(y)傳回是“true”,而且y.equals(z)傳回是“true”,那麼z.equals(x)也應該傳回是“true”。 

|---- 還有一緻性:如果x.equals(y)傳回是“true”,隻要x和y内容一直不變,不管你重複x.equals(y)多少次,傳回都是“true”。 

|---- 任何情況下,x.equals(null),永遠傳回是“false”;x.equals(和x不同類型的對象)永遠傳回是“false”。 

String中的方法:

常見字元串操作:

1.   擷取

|----字元串中包含的字元數,也就是字元串的長度int length()(數組有長度但是是屬性,通過arr.length傳回這個屬性來完成。而這裡是一個方法,帶(),功能是擷取長度。)

|----根據位置擷取位置上某個字元。

  CharcharAt(int index):

|----根據換字元擷取該字元串中的位置。

IntindexOf (int ch):傳回的是ch在字元串中第一次出現的位置。當通路到字元串中不存在的角标時會發生StringIndexOutOfBoundsException。字元角标越界。

int indexOf(intch, int fromIndex) :從fromIndex指定位置開始,擷取ch在字元串中出現的位置。如果ch值沒有出現在字元串中,輸出的值為-1

int indexOf(String str):傳回的是str在字元串中第一次出現的位置。

intindexOf(String str, int fromIndex) :從fromIndex指定位置開始,擷取str在字元串中出現的位置。String型,字元串應該用單引号’a’

int lastIndexOf(int ch):反向索引,輸出的結果還是正常的角标,隻不過系統會從後面往前數數。注意這裡是int型,字元串a應該加雙引号”a”

簡單例子:

1   

7 import java.util.Scanner;  

8   

9   

10 public class Lianxi {  

11 public static void main(String[] args) {  

12     //定義鍵盤輸入功能  

13     Scanner sc=new Scanner(System.in);  

14     //輸入字元串  

15     System.out.println("請輸入字元串:");  

16     //接收字元串  

17     String str=sc.nextLine();  

18     //定義計數器  

19     int big=0;  

20     int num=0;  

21     int small=0;  

22     //周遊字元判斷類型  

23     for(int x=0;x<str.length();x++){  

24         char ch=str.charAt(x);  

25         if(ch>='a'&&ch<='z'){  

26             small++;  

27         }  

28         else if(ch>='A'&&ch<='Z'){  

29             big++;  

30         }  

31         else{  

32             num++;  

33         }  

34     }  

35     System.out.println("大寫字母個數:"+big);  

36     System.out.println("小寫字母個數:"+small);  

37     System.out.println("數字個數:"+num);  

38 }  

39 }  

2,判斷。

     |----字元串中是否包含某一個子串。(兩個方法)

           boolean contains(str):

           特殊之處重要掌握:indexOf(str):可以索引str第一次出現位置,如果傳回-1.表示該str不在字元串中存在。是以,也可以用于對指定判斷是否包含。

                      if(str.indexOf("aa")!=-1)

           而且該方法即可以判斷,有可以擷取出現的位置。

     |----字元中是否有内容。

           boolean isEmpty(): 原理就是判斷長度length()是否為0.

     |---- 字元串是否是以指定内容開頭。

           boolean startsWith(str);

     |---- 字元串是否是以指定内容結尾。

           boolean endsWith(str);

     |---- 判斷字元串内容是否相同。複寫了Object類中的equals方法。不忽略大小寫           boolean equals(str);

     |---- 判斷内容是否相同,并忽略大小寫。

           boolean equalsIgnoreCase();

3,轉換。

  |----将字元數組轉成字元串。

      構造函數:String(char[])

      String(char[],offset,count):将字元數組中的一部分轉成字元串。

      Offset是角标,count是個數,從offset開始後面的count數目的數組内容轉換成字元串。如果有對象建立,放到新的對象裡面

char[] arr = {'a','b','c','d','e','f'};

           String s= new String(arr,1,3);

           sop("s="+s);

           輸出結果是s=bcd

      靜态方法:

           static String copyValueOf(char[]);

           static String copyValueOf(char[]data, int offset, int count)

           static String valueOf(char[]):

           要回去找這些方法并使用。靜态的方法是因為方法内部沒有特殊變量

  |----将字元串轉成字元數組。**

           char[] toCharArray():

  |---- 将位元組數組轉成字元串。

                 String(byte[])一定要記住這個函數

                 String(byte[],offset,count):将位元組數組中的一部分轉成字元串。

  |---- 将字元串轉成位元組數組。

                 byte[]  getBytes():

  |---- 将基本資料類型轉成字元串。

           static String valueOf(int)

           static String valueOf(double)

           //3+"";//String.valueOf(3);這兩個的意思是一樣的。3和空字元,後者比較準确,但比較麻煩,一般寫前者。

           特殊:字元串和位元組數組在轉換過程中,是可以指定編碼表的。

簡單例子:

40   

48 import java.util.Scanner;  

49   

50 public class Test {  

51     public static void main(String[] args) {  

52         // 封裝鍵盤錄入字元串  

53         Scanner sc = new Scanner(System.in);  

54         System.out.println("請輸入字元串:");  

55         String str = sc.nextLine();  

56         // 截取字元串  

57         String str1 = str.substring(0, 1);  

58         String str2 = str.substring(1, str.length());  

59         // 轉換大小寫  

60         String str3 = str1.toUpperCase();  

61         // 連接配接字元串  

62         String str4 = str3.concat(str2);  

63         System.out.println("str4=" + str4);  

64     }  

4,替換

      String replace(oldchar,newchar);

示例:

      String s = "Hello Java";

      String s1 = s.replace(‘a’,’n’);

      Sop(s);

      Sop(s1);

輸出結果是Hello Java和Hello Jnvn。因為s字元串用final修飾,不會變的。調用replace函數以後指派給了s1

如果用q替換n呢?沒有q,是以傳回的是原字元串

5,切割

      String[] split(regex);

示例: public static void method_split()

      {

           String s ="zhagnsa,lisi,wangwu";

           String[] arr  = s.split(",");//建立一個字元串數組,arr,用來放s切割後的字元串。

           for(int x = 0; x<arr.length; x++)

           {

                 sop(arr[x]);//列印數組

           }

      }

注意這是個分割函數,用’,’分割,這個逗号是拿不到的。

簡單例子:

65   

73 public class Demo {  

74     public static void main(String[] args) {  

75         // 輸入字元串  

76         String str1 = "basckd";  

77         // 轉換成字元數組  

78         char[] chs = str1.toCharArray();  

79         // 定義排序功能,選擇排序  

80         selectSort(chs);  

81         // 将字元數組轉換成字元串  

82         String str2 = String.valueOf(chs);  

83         System.out.println(str2);  

84     }  

85   

86     private static void selectSort(char[] chs) {  

87         for (int x = 0; x < chs.length - 1; x++) {  

88             for (int y = x + 1; y < chs.length; y++) {  

89                 if (chs[x] > chs[y]) {  

90                     char temp = chs[x];  

91                     chs[x] = chs[y];  

92                     chs[y] = temp;  

93                 }  

94             }  

95         }  

96   

97     }  

98 }  

6,子串。擷取字元串中的一部分。

      String substring(begin);

      String substring(begin,end);

示例     String s ="abcdef";

      sop(s.substring(2));//從指定位置開始到結尾。如果角标不存在,會出現字元串角标越界異常。

      sop(s.substring(2,4));//包含頭,不包含尾。

上面輸出的結果是cdef和cd。擷取所有的數組的就是s.substring(0,s.length());

7,轉換,去除空格,比較。

     |---- 将字元串轉成大寫或則小寫。

            String toUpperCase();

            String toLowerCase();

     |----将字元串兩端的多個空格去除。

           String trim();

     |---- 對兩個字元串進行自然順序的比較。

           int compareTo(string);

 2  StringBuffer、StringBuilder類 

StringBuffer是字元串緩沖區。是一個容器。可以對字元串内容進行增删。字元串的組成原理就是通過該類實作的。publicfinal class StringBuffer,同樣被final修飾,不能修改

特點:

1,長度是可變化的。

2,可以位元組操作多個資料類型。

3,最終會通過toString方法變成字元串。

數組的個數和類型是固定的,是以當數值類型和個數不固定時一般都用StringBuffer

特點:

1,長度是可變化的。

2,可以位元組操作多個資料類型。

3,最終會通過toString方法變成字元串。

1,存儲。

      StringBuffer append():将指定資料作為參數添加到已有資料結尾處。

Byte short沒有,因為接收int無法提升

      StringBuffer insert(index,資料):可以将資料插入到指定index位置。

示例:StringBuilder sb = new StringBuffer ();

      StringBuffer sb1 =sb.append(34);

      Sop(sb.toString());

      Sop(sb1.toString());

此時輸出結果一樣,并且sb==sb1,原因是StringBuffer是一個容器,放了sb,改變了sb為sb1,還是那個容器并沒有變。是以改變後兩者相等。并且可以這樣使用

      Sb.appen(“abc”).apend(34);方法調用鍊,方法使用後傳回的仍然為原來的對象可以繼續調用方法

      Sb.insert(1,”qq”)從第一位後插入qq這個字元串

2,删除。

      StringBuffer delete(start,end):删除緩沖區中的資料,包含start,不包含end。

      StringBuffer deleteCharAt(index):删除指定位置的字元。

      清空緩沖區的指令:sb.delete(0,sb.length());最大角标是length-1,因為這個delete指令包含頭不包含尾,是以是sb.length()。

3,擷取。

      char charAt(int index)

      int indexOf(String str)

      int lastIndexOf(String str)

      int length()

      String substring(int start, int end)

4,修改。

      StringBuffer replace(start,end,string);

      void setCharAt(int index, char ch) ;

5,反轉。

      StringBuffer reverse();

6,将緩沖區中指定資料存儲到指定字元數組中。

      void getChars(int srcBegin, int srcEnd,char[] dst, int dstBegin)

JDK1.5 版本之後出現了StringBuilder.

StringBuffer與StringBuilder的差別:StringBuffer是線程安全的,效率低;StringBuilder是線程不安全的,效率高

StringBuffer是線程同步。

StringBuilder是線程不同步。

以後開發,建議使用StringBuilder

更新三個因素:

1,提高效率。

2,簡化書寫。

3,提高安全性。

簡單例子:

99   

105 public class Lianxi {  

106     public static void main(String[] args) {  

107         int[] arr = { 3, 7, 9, 0, 5 };  

108         String str = arrayToString(arr);  

109         System.out.println(str);  

110     }  

111   

112     private static String arrayToString(int[] arr) {  

113         // 建立StringBuilder對象  

114         StringBuilder sb = new StringBuilder();  

115         // 周遊數組,添加字元串  

116         sb.append("[");  

117         for (int x = 0; x < arr.length; x++) {  

118             if (x != arr.length - 1) {  

119                 sb.append(arr[x] + ",");  

120             } else {  

121                 sb.append(arr[x] + "]");  

122             }  

123         }  

124         return sb.toString();  

125     }  

126 }  

 3  基本資料類型包裝類 

在許多情況下包裝與解包裝是由編譯器自行完成的(在這種情況下包裝成為裝箱,解包裝稱為拆箱); 

可了解了解自動裝箱就可以簡單的了解為将基本資料類型封裝為對象類型,來符合java的面向對象;

 例如用int:

Integer num = 10; //聲明一個Integer對象 此聲明就是用到了自動的裝箱:解析為

Integer num = new Integer(10);以上就是一個很好的展現,因為10是屬于基本資料類型的,原則上它是

 不能直接指派給一個對象Integer的,但jdk1.5後你就可以進行這樣的聲明,這就是自動裝箱的魅力 

自動将基本資料類型轉化為對應的封裝類型。成為一個對象以後就可以調用對象所聲明的所有的方法 

自動拆箱:故名思議就是将對象重新轉化為基本資料類型:

Integer num = 10;//裝箱  

int num1 = num;//拆箱 

自動拆箱有個很典型的用法就是在進行運算的時候:因為對象時不能直接進行運算的,而是要轉化為基本資料類型後才能進行加減乘除 。 

Integer num = 10; 

//進行計算時隐含的有自動拆箱 

System.out.print(num--);

 在-128~127 之外的數 

                 Integer num1 = 297; Integer num2 = 297; //在-128~127 之外的數

                System.out.println("num1==num2: "+(num1==num2)); //num1==num2: false 

                 Integer num3 = 97; Integer num4 = 97;// 在-128~127 之内的數

                 System.out.println("num3==num4: "+(num3==num4)); //num3==num4: true

說明:

加大對簡單數字的重利用,java定義:在自動裝箱時對于值從–128到127之間的值,它們被裝箱。

這就歸結于java對于Integer與int的自動裝箱與拆箱的設計,是一種模式:叫享元模式(flyweight)

為Integer對象後,會存在記憶體中被重用,始終隻存在一個對象 而如果超過了從–128到127之間

的值,被裝箱後的Integer對象并不會被重用,即相當于每次裝箱時都建立一個 Integer對象。

自動裝箱拆箱不僅在基本資料類型中有應用,在String類中也有應用:

               String str = "sl"; 

               //代替下面的聲明方式 

               String str = new String("sl");

     例題 1、 Integer a = new Integer(100);     Integer b = 100; Integer c =100; int d = 100;a、b、c、d這四個數通過“==”和equals方法,進行比較,都哪些結果是true,哪些是false?

public class T1 {

 public static void main(String[] args) {

   Integer a = new Integer(100);

   Integer b = 100;     

   Integer c =100;     

   int d = 100;

 // 下面是測試證明“==”

   System.out.println(d==a);  //true

   System.out.println(d==b);   //true

   System.out.println(d==c);    //true

   System.out.println(a==b) ;//false

   System.out.println(a==c);//false

   System.out.println(b==c);//true

 // 下面是測試證明“equals”

    // System.out.println(d.equals(a));//不能調用基本類型 int 的 equals(Integer)

    // System.out.println(d.equals(b));//不能調用基本類型 int 的 equals(Integer)

    // System.out.println(d.equals(c));//不能調用基本類型 int 的 equals(Integer)

   System.out.println(b.equals(c));//true

   System.out.println(a.equals(b));//true

   System.out.println(a.equals(c));//true

   System.out.println(a.equals(d));//true  

   System.out.println(b.equals(d));//true

   System.out.println(c.equals(d));//true

 }

}

講解:

1.  d==a;d==b;d==c;為true

            因為JDK1.5版本以後的新特性可以可以Integer對象自動拆箱成為int型變量,是以結果為true。

2.   a==b與a==c;為false,

          因為b和c為自動裝箱後才生的兩個新對象,該對象與a不是同一對象。

3.  b==c為true

           因為他們都是由int型變量自動裝箱而來,他們的比較是先拆箱還原成int型變量之後才進行比較,由于d為int型變量,不是對象,沒有equals方法,是以不能和a,b,c對象做比較。

4.   b.equals(c);a.equals(b);a.equals(c);都為true

          因為equals隻針對對象的内容進行比較。

5.  a.equals(d);b.equals(d);c.equals(d) 都為true

           因為此時的int型變量被自動裝箱為Integer對象,而equals隻針對對象的内容進行比較。

總結:

操作字元串的方法有很多,剛開始學的時候感覺知識點太多了,但學完一回顧大緻也就分為四類,增删改查.StringBuffer和StringBuilder的差別就在于是否是線程安全,線程安全的有同步代碼,每次運作都需要判斷同步鎖,效率相比之下也就比較低

基本資料類型:

1.在進行編譯時,編譯器再自動根據您寫下的語句,判斷是否進行自動裝箱動作。

在上例中integer參考的會是Integer類的執行個體。同樣的動作可以适用于 boolean、

byte、short、char、long、float、double等基本資料類型,分别會使用對應的打

包類型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。

2.在JAVA中利用"=="比較變量時,系統使用變量在"棧"中所存的值作為比較的依據。

基本資料類型在"棧"中存的是其内容值,而對象類型在"棧"中存的是位址,這些位址指向"堆"中的對象。==隻針對變量的值;equals隻針對對象的内容。

本篇博文結束!

                                                                                                   @感謝老師的辛苦批閱