前言

  看了一篇文章,大概是讲面试中的java基础的,有如题这么个面试题。我又翻了一些文章看了下,然后去看源码。看一下源码大概能更加了解一些。

String

  String类是final的,表示不可被继承,不可变的。注释上也有说明:

  

  其中用一个char[]来保存String的值。

 private final char value[];

  一旦赋值,就不可改变。看一下,操作string的源码,例如 substringreplaceconcat 等方法,最终结果都是返回 new String(...). 也就是重新创建了一个String对象。

 public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}

  

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

  

public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */ while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}

StringBuffer 和 StringBuilder

  它两个都是继承自 AbstractStringBuilder 抽象类,不同的是StringBuffer类都是带有 synchronized 关键字的。也就是说,StringBuffer是线程安全的,而 StringBuilder不是。他们中的方法基本上调用 super的方法。也就是AbstractStringBuilder 里实现的方法

  平时用的比较多的就是 append 方法。我们看一下代码实现:

 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 void ensureCapacityInternal(int minimumCapacity) {
// 当append之后的长度大于当前value的长度的时候,需要重新生成一个char[]数组。
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}

 

 public static char[] copyOf(char[] original, int newLength) {
     //重新创建一个char[]数组
char[] copy = new char[newLength];
    //将之前的值赋值到该数组中
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}

  

 ensureCapacityInternal 方法中,将 value的值重新扩展比如  str.append("abc")。假如之前value的值为:{'h','e','l','l','o'},当调用 str.getChars方法之后,会将 abc 追加到value数组后,value值就变成 :{'h','e','l','l','o','a','b','c'}

 其实 getChars 方法只是做了一件事情 :System.arraycopy。

 如图:

 执行完arraycopy之后

总结

  String 不可变,StringBuffer和StringBuilder可变,但是StringBuilder非线程安全。可以根据他们不同的特性分情况使用。

最新文章

  1. Python 进程间通信
  2. 如何下载youtube上面的视频
  3. 第七节:Class与Style绑定
  4. display:inline-block 去除间隙
  5. JQuery.getJSON 从aspx页面返回JSON数据
  6. js判断IE浏览器版本
  7. oracle中between
  8. .NET Framework 4.5、4.5.1 和 4.5.2 中的新增功能
  9. 如何用C#代码查找某个路径下是否包含某个文件
  10. bzoj3555: [Ctsc2014]企鹅QQ
  11. Android(java)学习笔记203:网页源码查看器(Handler消息机制)
  12. 尚学堂Java面试题整理
  13. Visual Studio 2012的开发使用技巧
  14. APP品牌具体有哪几个要素?又是如何操作的?
  15. 『开源』扩展 JS 的 Date 处理函数
  16. python下调用pytesseract识别某网站验证码
  17. MSSQL 转 ACCESS 在表格结构上应注意的
  18. NIO框架之MINA源码解析(五):NIO超级陷阱和使用同步IO与MINA通信
  19. 关于text-align和text-align-last
  20. Deque 双端队列 Stack 堆栈

热门文章

  1. Spring学习笔记:Spring动态组装打印机
  2. python __new__()分析
  3. Csharp: speech to text, text to speech in win
  4. 23_ConcurrentLinkedQueue
  5. 如何实现Docker应用的自定义弹性伸缩
  6. Raspberry Config.txt 介绍
  7. Android网络通信库Volley简介(转)
  8. 4 关于word2vec的skip-gram模型使用负例采样nce_loss损失函数的源码剖析
  9. 记重回IT行业的面试
  10. Day02——Python基本数据类型