java String部分源碼解析

來源:互聯網
上載者:User

標籤:

String類型的成員變數

/** String的屬性值 */      private final char value[];    /** The offset is the first index of the storage that is used. */    /**數組被使用的開始位置**/    private final int offset;    /** The count is the number of characters in the String. */    /**String中元素的個數**/    private final int count;    /** Cache the hash code for the string */   /**String類型的hash值**/    private int hash; // Default to 0    /** use serialVersionUID from JDK 1.0.2 for interoperability */    private static final long serialVersionUID = -6849794470754667710L;

   有上面的成員變數可以知道String類的值是final類型的,不能被改變的,所以只要一個值改變就會產生一個新的String類型對象,儲存String資料也不一定從數組的第0個元素開始的,而是從offset所指的元素開始。

如下面的代碼是產生了一個新的對象,最後的到的是一個新的值為“bbaa”的新的String的值。

     String a = new String("bb");     String b = new String("aa");     String c =  a + b;    

 

  也可以說String類型的對象是長度不可變的,String拼接字串每次都要產生一個新的對象,所以拼接字串的效率肯定沒有可變長度的StringBuffer和StringBuilder快。

 

然而下面這種情況卻是很快的拼接兩個字串的:

    String a = "aa" + "bb";

  原因是:java對它字串拼接進行了小小的最佳化,他是直接把“aa”和“bb”直接拼接成了“aabb”,然後把值賦給了a,只需產生一次String對象,比上面那種方式減少了2次產生String,效率明顯要高很多。

 

 

下面我們來看看String的幾個常見的構造方法

 

1、無參數的構造方法:

public String() {    this.offset = 0;    this.count = 0;    this.value = new char[0];    }

 

 

2、傳入一個Sring類型對象的構造方法

public String(String original) {    int size = original.count;    char[] originalValue = original.value;    char[] v;      if (originalValue.length > size) {         // The array representing the String is bigger than the new         // String itself.  Perhaps this constructor is being called         // in order to trim the baggage, so make a copy of the array.            int off = original.offset;            v = Arrays.copyOfRange(originalValue, off, off+size);     } else {         // The array representing the String is the same         // size as the String, so no point in making a copy.        v = originalValue;     }    this.offset = 0;    this.count = size;    this.value = v;    }

 

 

 3、傳入一個字元數組的建構函式

public String(char value[]) {    int size = value.length;    this.offset = 0;    this.count = size;    this.value = Arrays.copyOf(value, size);    }

 

 

4、傳入一個字串數字,和開始元素,元素個數的建構函式

public String(char value[], int offset, int count) {        if (offset < 0) {            throw new StringIndexOutOfBoundsException(offset);        }        if (count < 0) {            throw new StringIndexOutOfBoundsException(count);        }        // Note: offset or count might be near -1>>>1.        if (offset > value.length - count) {            throw new StringIndexOutOfBoundsException(offset + count);        }        this.offset = 0;        this.count = count;        this.value = Arrays.copyOfRange(value, offset, offset+count);    }

 

   由上面的幾個常見的建構函式可以看出,我們在產生一個String對象的時候必須對該對象的offset、count、value三個屬性進行賦值,這樣我們才能獲得一個完成的String類型。

 

 

常見函數:

 

1、判斷兩個字串是否相等的函數(Equal):其實就是首先判斷比較的執行個體是否是String類型資料,不是則返回False,是則比較他們每一個字元元素是否相同,如果都相同則返回True,否則返回False

public boolean equals(Object anObject) { if (this == anObject) {     return true; } if (anObject instanceof String) {     String anotherString = (String)anObject;     int n = count;     if (n == anotherString.count) {  char v1[] = value;  char v2[] = anotherString.value;  int i = offset;  int j = anotherString.offset;  while (n-- != 0) {      if (v1[i++] != v2[j++])   return false;  }  return true;     } } return false;    }

 

 

 2、比較兩個字串大小的函數(compareTo):輸入是兩個字串,返回的0代表兩個字串值相同,返回小於0則是第一個字串的值小於第二個字串的值,大於0則表示第一個字串的值大於第二個字串的值。

  比較的過程主要如下:從兩個字串的第一個元素開始比較,實際比較的是兩個char的ACII碼,加入有不同的值,就返回第一個不同值的差值,否則返回0

public int compareTo(String anotherString) { int len1 = count; int len2 = anotherString.count; int n = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; if (i == j) {     int k = i;     int lim = n + i;     while (k < lim) {  char c1 = v1[k];  char c2 = v2[k];  if (c1 != c2) {      return c1 - c2;  }  k++;     } } else {     while (n-- != 0) {  char c1 = v1[i++];  char c2 = v2[j++];  if (c1 != c2) {      return c1 - c2;  }     } } return len1 - len2;    }
View Code

 

 

 3、判斷一個字串是否以prefix字串開頭,toffset是相同的長度

public boolean startsWith(String prefix, int toffset) { char ta[] = value; int to = offset + toffset; char pa[] = prefix.value; int po = prefix.offset; int pc = prefix.count; // Note: toffset might be near -1>>>1. if ((toffset < 0) || (toffset > count - pc)) {     return false; } while (--pc >= 0) {     if (ta[to++] != pa[po++]) {         return false;     } } return true;    } public int hashCode() { int h = hash; if (h == 0) {     int off = offset;     char val[] = value;     int len = count;            for (int i = 0; i < len; i++) {                h = 31*h + val[off++];            }            hash = h;        }        return h;    }

 

 

 4、串連兩個字串(concat)

public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) {     return this; } char buf[] = new char[count + otherLen]; getChars(0, count, buf, 0); str.getChars(0, otherLen, buf, count); return new String(0, count + otherLen, buf);    }

 

 

 連接字串的幾種方式

1、最直接,直接用+串連

     String a = new String("bb");     String b = new String("aa");     String c =  a + b;

 

 

 2、使用concat(String)方法

      String a = new String("bb");      String b = new String("aa");       String d = a.concat(b);

 

 

3、使用StringBuilder

 String a = new String("bb"); String b = new String("aa");     StringBuffer buffer = new StringBuffer().append(a).append(b);

 

   第一二中用得比較多,但效率比較差,使用StringBuilder拼接的效率較高。

 

java String部分源碼解析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.