Java String 解析
1. String为什么是不可变对象
首先String不属于8种基本数据类型,String是一个对象。
内部成员变量
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
}
可以看出String的内部是采用char数组实现的,而且value被声明为final类型,标明其在初始化后value值不能被改变,由此可以看出String是不可变得。
但是其并不是完全不可变得,通过反射技术可以改变String的值 如下:
String count = new String("1");
Class<?> stringClass = Class.forName("java.lang.String");
Field field =stringClass.getDeclaredField("value");
//设置私有成员可见性
field.setAccessible(true);
//获取原值
char[] test = (char[])field.get(count);
//修改
test[0]='2';
//count被修改成2
System.out.println(count.toString());
2. String str = “test” 与String str = new String(“test”)的区别;
String str = “test”字面量创建形成:
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。
String str = new String(“test”)正常创建
会在堆上分配内存,栈上分配引用
- 堆:存放所有new出来的对象
- 栈:存放基本类型的变量数据和对象的应用,对象(new出来的对象)本身并不存在栈中,而是存放在堆中或者常量池中(字符串常量对象存放在常量池中)
- 常量池:存放基本类型常量和字符串常量。
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。