String中的相关问题
String string = "abcd";
String string2 = new String(string);
String string3 = new String("abcd");
1. “” 和 new创建字符串的区别
通过javap -c -l -s -verbose xxx.class得出字节码
如图所示,我们看到字节码中有常量池ConstantPool,String string = "abcd"
,首先在常量池中有一个“abcd”的String,在main函数中ldc(load constant),在栈中维持一个对它的引用。
string2 = new String(string)
,首先String string2
,只是定义一个string2的String变量,并没有创建对象;先调用new关键字,创建一个String对象,此时并没有初始化,还没有执行构造函数;然后将第一行string变量“aload_1”,调用构造函数
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
最后执行“==”,将创建好的String对象赋值给string2 。
2. string中“+”的实现
String string = "abcd";
String string2 = new String(string);
String string3 = new String("abcd");
String string4 = string+"zxc";
String string5 = string2+"zxc";
String string6 = "abcd"+"zxc";
看字节码:
这里constant pool中有3个字符串常量
通过字节码发现String string4 = string+"zxc"
和String string5 = string2+"zxc"
都是通过StringBuilder实现的,看一下StringBuilder代码:
public StringBuilder() {//无参构造函数
super(16);
}
@Override
public StringBuilder append(String str) {
super.append(str);//调用父类append函数
return this;
}
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;
}
从字节码中也可以看出来,这两者的不同之处在于+号前面部分的aload指令不同。
那为什么String string6 = "abcd"+"zxc"
没有使用StringBuilder实现,这是因为在编译期间,JVM就已经知道了具体的数值,故在常量池中就已经存在“abcdzxc”的常量,直接引用即可。
- hashCode()
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}