【JAVA - 基础】之String存储机制浅析
2018-01-08 14:19
453 查看
本文主要解决以下几个问题
String源码解析?String和new String的区别?
String通过“+”或concat累加时的对象创建机制?
StringBuilder和StringBuffer?区别和联系?
String源码解析
String类的定义
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ...... }
通过上面的代码可以得出以下结论:
String类使用
final关键字修饰,表示String类是最终类,不可以被继承;
String类是CharSequence的一个实现类;
String类实现了Serializable接口,表示String类可以被序列化;
String类实现了Comparable接口,表示String类对象之间可以直接进行比较
String#value
/** The value is used for character storage. */ private final char value[];
String中的value属性用于字符存储;
String中的value属性使用final关键字修饰,表示value不可变
由于value不可变,因此,String对象具有以下两个特点:
String对象地址不可变(Immutable)
String对象是线程同步的(can be shared)
String#concat()
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); }
不管上面对字符串进行了什么处理,只看最后一行,返回了一个
new String,因此,concat()方法实际上是返回了一个新的字符串。也就是说,每次调用concat()方法时,concat()方法中的参数会生成一个新的字符串变量,执行后得到的新字符串又是一个新的字符串变量。使用“+”进行字符串累加时也是一样的机制。
String和new String的区别
Java虚拟机中用于存储的区域分为栈、堆和方法区,方法区中包括另一片区域,称为常量池。String的存储主要涉及到的存储区域就是堆、栈和常量池。栈中主要存储的是简单类型的变量和引用类型变量的存储地址;堆中存储的是引用类型数据本身;常量池中存储的是常量。
String变量的声明和定义方式有两种:
String str1 = new String("mystr");
String str2 = "mystr";
以上两种创建String对象的方式的区别是:
运行时机的不同:第一种方式中有new关键字,是在程序运行期间才会执行的;而第二种方式是在编译期间就执行了;
创建对象过程的不同:使用第一种方式创建String对象时,首先在堆中创建一个String对象,然后在栈中开辟一片空间,指向堆中的这一片区域,最后去常量池中寻找是否存在这个字符串常量,如果不存在,则在常量池中创建一个;使用第二种方式创建String对象时,会直接去常量池中寻找是否有这个字符串常量,如果有则直接引用到栈中,如果没有则先创建一个再引用到栈中。
通过上一点可以得出结论:通过第一种方式创建String对象之后,在堆中、常量池中分别有一个对象,因此是创建了一个或两个对象;通过第二种方式创建String对象之后,在常量池中有一个对象,因此是创建了零个或一个对象;
使用第一种方式,栈中的指针指向的是堆中的对象;使用第二种方式,栈中的指针指向的是常量池中的对象
StringBuilder和StringBuffer
前面说到,使用“+”和concat()方法对字符串进行拼接的时候,会创建额外的字符串变量,因此,当我们需要进行字符串拼接的时候,比较提倡的方法是使用StringBuilder或StringBuffer。StringBuilder和StringBuffer中都提供了append()方法,可以实现字符串的拼接。
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
StringBuilder和StringBuffer都继承自AbstractStringBuilder,其底层依然是一个char数组,但不是final类型的。
// StringBuffer # append() public synchronized StringBuffer append(CharSequence s) { toStringCache = null; super.append(s); return this; }
// StringBuilder # append() public StringBuilder append(CharSequence s) { super.append(s); return this; }
从上面的StringBuffer和StringBuilder的append()方法的源码比较中可以发现,两个类中append()方法唯一的区别就是,StringBuffer中的append()方法添加了
synchronized关键字,表示这个方法是线程同步的。
通过上面的分析得到结论:StringBuffer是线程安全的,而StringBuilder是线程不安全的。
由于StringBuilder是线程不安全的,因此StringBuilder处理字符串的性能要比StringBuffer高。
相关文章推荐
- Java基础-String 存储机制管理
- java基础--浅析java中序列化机制
- Java基础之字符串创建于存储的机制
- Java基础小技巧回顾--浅析String
- 关于java基础类型与引用类型内存存储问题,以及string.intern()方法(String两种创建方式的区别)
- 浅析Java多线程程序设计机制-Java基础-Java-编程开发
- 【java基础】浅析String
- 【Java基础】JAVA不可变类(immutable)机制与String的不可变性
- Java基础---浅析String,StringBuilder,StringBuffer的区别
- 栈(stack)与堆(heap)区别以及Java的string变量赋值的内部工作机制(精典转载贴)
- int 和 String 互相转换的多种方法-Java基础-Java-编程开发
- 浅析Java语言中两种异常的差别-Java基础-Java-编程开发
- JAVA基础--JAVA中的反射机制详解
- java基础--特殊的String
- 栈(stack)与堆(heap)区别以及Java的string变量赋值的内部工作机制(精典转载贴)
- 浅析Java与C#的事件处理机制
- java基础--特殊的String
- 深入分析java中webwork中的文件上传机制-Java基础-Java-编程开发
- Java基础:JAVA程序类加载及其反射机制
- 浅析Java多线程程序设计机制