Heim > Fragen und Antworten > Hauptteil
String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = new String("a");
String str5 = new String("b");
String str6= new String("ab");
String plus1 = str1 + str2;
String plus2 = str1 + "b";
String plus3 = str4 + "b";
String plus4 = "a" + "b";
String plus5 = str4 + str5;
String plus6 = str4 + str2;
string相加有上面的6种情况
我想弄清楚各种情况的区别,我知道的是plus4都是在栈区,所以结果是一个字符串常量池里的常量,但是其他情况呢?
另外,我打印plus1~plus6的地址或者hashcode,发现都是一样的,怎么回事?
PHP中文网2017-04-18 10:32:17
一楼回答太笼统,而且抛开JVM和JDK版本谈内存分配都是耍流氓。
以提问的为例:
String str1 = "a";
String str2 = "b";
String str3 = "ab";
这种直接定义字符串,JVM认为字符串是不变量,也就是线程安全的,因为这种字符串直接分配在方法区的常量池中.
String str4 = new String("a");
String str5 = new String("b");
String str6= new String("ab");
有new关键字,说明这种字符串是分配在堆上.可以使用如下方法验证:
public static void main(String[] args) {
String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = new String("a");
String str5 = new String("b");
String str6= new String("ab");
System.out.println(str1 == str4); // false,说明str1和str4的内存地址不一样,一个在方法区,一个在堆.
System.out.println(str1 == str4.intern()); // true,str4存入常量池后并没有重新创建一块内存,而是使用了已有的常量句柄.
}
回答一下为什么plus1~6的hashcode一样,是因为你没有去重写String的hashcode方法。而String默认hashcode的实现为:
@Override public int hashCode() {
int hash = hashCode;
if (hash == 0) {
if (count == 0) {
return 0;
}
for (int i = 0; i < count; ++i) {
hash = 31 * hash + charAt(i);
}
hashCode = hash;
}
return hash;
}
只是对字面常量做了处理,而plus1~6的字面常量一样,所以hashcode值当然一致。然后hashcode一致,不代表它们在jvm分配的内存地址一致。
ringa_lee2017-04-18 10:32:17
相同字符串在内存中只有一个实例
------------------------------分割线----------------
本答案过于笼统,且有误导之嫌,请大家移步正一兄的回答
大家讲道理2017-04-18 10:32:17
楼上说的对,相同字符串字面量在方法区中只会有一个值。这个也就是常说的string和stringbuffer的用法区别。
下面我补充:
String str4 = new String("a");
“a”字面量是储存在jvm的方法区中。
str4这个对象是存储在堆中。
上面这句话意思就有2个内存地址被分配。
而栈中存储的是8中基本类型和returnAddress、reference,字符串是不会存储在栈中。
关于hashcode用法呢,就是用来匹配和定位的。你可以去自己去百度hashcode 和 == 和 equals的区别。
而且,plus1-6的内存地址肯定是不一样的。我不知道你怎么发现是一样的。。。
如果有什么理解的不对的,忘各位大牛指点一二。