最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

String,stringbuilder和stringbuffer源码分析

互联网 admin 11浏览 0评论

String,stringbuilder和stringbuffer源码分析

String,stringbuilder和stringbuffer源码分析

前几天回南京面试暑期实习,人家问了我string和builder,buffer之间的区别,我其实当时是没有看过这几个类的源码的,只是知道一点点原理,而且我面试不喜欢背题,所以很不幸面试结果不是很好,这次回家了,好好看看这几个类的源码。

string

string的话据我所知Java8和Java9之间有了一些改变,我自己看了Jdk8和jdk11的string源码这里只贴出8的部分代码。

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];

从上面可以看出来8的里面是固定的char数组来实现的,我看的11的话是byte数组实现的

下面贴两个常用方法

public String trim() {int len = value.length;int st = 0;char[] val = value;    /* avoid getfield opcode */while ((st < len) && (val[st] <= ' ')) {st++;}while ((st < len) && (val[len - 1] <= ' ')) {len--;}return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}public String toUpperCase(Locale locale) {if (locale == null) {throw new NullPointerException();}int firstLower;final int len = value.length;/* Now check if there are any characters that need to be changed. */scan: {for (firstLower = 0 ; firstLower < len; ) {int c = (int)value[firstLower];int srcCount;if ((c >= Character.MIN_HIGH_SURROGATE)&& (c <= Character.MAX_HIGH_SURROGATE)) {c = codePointAt(firstLower);srcCount = Character.charCount(c);} else {srcCount = 1;}int upperCaseChar = Character.toUpperCaseEx(c);if ((upperCaseChar == Character.ERROR)|| (c != upperCaseChar)) {break scan;}firstLower += srcCount;}return this;}/* result may grow, so i+resultOffset is the write location in result */int resultOffset = 0;char[] result = new char[len]; /* may grow *//* Just copy the first few upperCase characters. */System.arraycopy(value, 0, result, 0, firstLower);String lang = locale.getLanguage();boolean localeDependent =(lang == "tr" || lang == "az" || lang == "lt");char[] upperCharArray;int upperChar;int srcChar;int srcCount;for (int i = firstLower; i < len; i += srcCount) {srcChar = (int)value[i];if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&(char)srcChar <= Character.MAX_HIGH_SURROGATE) {srcChar = codePointAt(i);srcCount = Character.charCount(srcChar);} else {srcCount = 1;}if (localeDependent) {upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);} else {upperChar = Character.toUpperCaseEx(srcChar);}if ((upperChar == Character.ERROR)|| (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {if (upperChar == Character.ERROR) {if (localeDependent) {upperCharArray =ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);} else {upperCharArray = Character.toUpperCaseCharArray(srcChar);}} else if (srcCount == 2) {resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;continue;} else {upperCharArray = Character.toChars(upperChar);}/* Grow result if needed */int mapLen = upperCharArray.length;if (mapLen > srcCount) {char[] result2 = new char[result.length + mapLen - srcCount];System.arraycopy(result, 0, result2, 0, i + resultOffset);result = result2;}for (int x = 0; x < mapLen; ++x) {result[i + resultOffset + x] = upperCharArray[x];}resultOffset += (mapLen - srcCount);} else {result[i + resultOffset] = (char)upperChar;}}return new String(result, 0, len + resultOffset);}

stringbuilder

stringbuilder源码很短而且里面大多数的方法都是对他的父类AbstractStringBuilder一系列方法的包装。

这里我仔细的看了几遍append这个方法,这些个方法都有很多的重载方法,这里拿出来一个string作为参数的append来看。

AbstractStringBuilder(int capacity) {value = new char[capacity];}public AbstractStringBuilder append(String str) {if (str == null)return appendNull();int len = str.length();ensureCapacityInternal(count + len);str.getChars(0, len, value, count);count += len;return this;
}
private AbstractStringBuilder appendNull() {int c = count;ensureCapacityInternal(c + 4);final char[] value = this.value;value[c++] = 'n';value[c++] = 'u';value[c++] = 'l';value[c++] = 'l';count = c;return this;}
private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0) {value = Arrays.copyOf(value,newCapacity(minimumCapacity));}}

他的value也是一个char数组。这样我们就可以看出来,在某种程度上stringbuilder和list是一样的,不过stringbuilder是一个可变数组,我们可以像使用list一样先设置一个容量比较大的char数组,这样在append时候就不用使用arrays.copyof方法了。如果容量不够了的话这里就需要扩容这个数组。

stringbuffer

stringbuffer这个类和builder的最大区别就是他的方法是synchronized标记的。

public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;
}

他也是对abstractstringbuilder的一系列方法的封装,整体上看和stringbuilder是一摸一样的

String,stringbuilder和stringbuffer源码分析

String,stringbuilder和stringbuffer源码分析

前几天回南京面试暑期实习,人家问了我string和builder,buffer之间的区别,我其实当时是没有看过这几个类的源码的,只是知道一点点原理,而且我面试不喜欢背题,所以很不幸面试结果不是很好,这次回家了,好好看看这几个类的源码。

string

string的话据我所知Java8和Java9之间有了一些改变,我自己看了Jdk8和jdk11的string源码这里只贴出8的部分代码。

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];

从上面可以看出来8的里面是固定的char数组来实现的,我看的11的话是byte数组实现的

下面贴两个常用方法

public String trim() {int len = value.length;int st = 0;char[] val = value;    /* avoid getfield opcode */while ((st < len) && (val[st] <= ' ')) {st++;}while ((st < len) && (val[len - 1] <= ' ')) {len--;}return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}public String toUpperCase(Locale locale) {if (locale == null) {throw new NullPointerException();}int firstLower;final int len = value.length;/* Now check if there are any characters that need to be changed. */scan: {for (firstLower = 0 ; firstLower < len; ) {int c = (int)value[firstLower];int srcCount;if ((c >= Character.MIN_HIGH_SURROGATE)&& (c <= Character.MAX_HIGH_SURROGATE)) {c = codePointAt(firstLower);srcCount = Character.charCount(c);} else {srcCount = 1;}int upperCaseChar = Character.toUpperCaseEx(c);if ((upperCaseChar == Character.ERROR)|| (c != upperCaseChar)) {break scan;}firstLower += srcCount;}return this;}/* result may grow, so i+resultOffset is the write location in result */int resultOffset = 0;char[] result = new char[len]; /* may grow *//* Just copy the first few upperCase characters. */System.arraycopy(value, 0, result, 0, firstLower);String lang = locale.getLanguage();boolean localeDependent =(lang == "tr" || lang == "az" || lang == "lt");char[] upperCharArray;int upperChar;int srcChar;int srcCount;for (int i = firstLower; i < len; i += srcCount) {srcChar = (int)value[i];if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&(char)srcChar <= Character.MAX_HIGH_SURROGATE) {srcChar = codePointAt(i);srcCount = Character.charCount(srcChar);} else {srcCount = 1;}if (localeDependent) {upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);} else {upperChar = Character.toUpperCaseEx(srcChar);}if ((upperChar == Character.ERROR)|| (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {if (upperChar == Character.ERROR) {if (localeDependent) {upperCharArray =ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);} else {upperCharArray = Character.toUpperCaseCharArray(srcChar);}} else if (srcCount == 2) {resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;continue;} else {upperCharArray = Character.toChars(upperChar);}/* Grow result if needed */int mapLen = upperCharArray.length;if (mapLen > srcCount) {char[] result2 = new char[result.length + mapLen - srcCount];System.arraycopy(result, 0, result2, 0, i + resultOffset);result = result2;}for (int x = 0; x < mapLen; ++x) {result[i + resultOffset + x] = upperCharArray[x];}resultOffset += (mapLen - srcCount);} else {result[i + resultOffset] = (char)upperChar;}}return new String(result, 0, len + resultOffset);}

stringbuilder

stringbuilder源码很短而且里面大多数的方法都是对他的父类AbstractStringBuilder一系列方法的包装。

这里我仔细的看了几遍append这个方法,这些个方法都有很多的重载方法,这里拿出来一个string作为参数的append来看。

AbstractStringBuilder(int capacity) {value = new char[capacity];}public AbstractStringBuilder append(String str) {if (str == null)return appendNull();int len = str.length();ensureCapacityInternal(count + len);str.getChars(0, len, value, count);count += len;return this;
}
private AbstractStringBuilder appendNull() {int c = count;ensureCapacityInternal(c + 4);final char[] value = this.value;value[c++] = 'n';value[c++] = 'u';value[c++] = 'l';value[c++] = 'l';count = c;return this;}
private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0) {value = Arrays.copyOf(value,newCapacity(minimumCapacity));}}

他的value也是一个char数组。这样我们就可以看出来,在某种程度上stringbuilder和list是一样的,不过stringbuilder是一个可变数组,我们可以像使用list一样先设置一个容量比较大的char数组,这样在append时候就不用使用arrays.copyof方法了。如果容量不够了的话这里就需要扩容这个数组。

stringbuffer

stringbuffer这个类和builder的最大区别就是他的方法是synchronized标记的。

public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;
}

他也是对abstractstringbuilder的一系列方法的封装,整体上看和stringbuilder是一摸一样的

发布评论

评论列表 (0)

  1. 暂无评论