为了账号安全,请及时绑定邮箱和手机立即绑定

Java: 不同String 相加在内存里的分布?

Java: 不同String 相加在内存里的分布?

慕哥9229398 2019-02-20 08:40:32
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,发现都是一样的,怎么回事?
查看完整描述

3 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

一楼回答太笼统,而且抛开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分配的内存地址一致。

查看完整回答
反对 回复 2019-03-01
?
函数式编程

TA贡献1807条经验 获得超9个赞

相同字符串在内存中只有一个实例

------------------------------分割线----------------

本答案过于笼统,且有误导之嫌,请大家移步正一兄的回答

查看完整回答
反对 回复 2019-03-01
  • 3 回答
  • 0 关注
  • 730 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信