详细对比Java字符串的存储方式

详细对比Java字符串的存储方式

结论:

  • 字符串常量存储在堆的常量池中,字符串对象存储在堆的非常量池中
  • 除了字符串对象之外,其他字符串都存储在常量池中。
  • 字符串对象相加产生另一个字符串对象。

字符串:

String name = "hello";

变量名name存储在jvm栈,值"hello"存储在堆中的常量池中

字符串对象:

String name2 = new String("hello");

变量名name2存储在jvm栈,值"hello"存储在堆的非常量池中,并且每个new出来的String对象的地址都是不同的

使用代码查看他们的地址是否相同:

String str1 = "abc";
String str2 = new String("abc");
System.out.println("常量与对象:" + str1 == str2);

//false

不过,可以把字符串对象的值从堆中挪到常量池中:

str2 = str2.intern();
System.out.println("字符串与intern后的字符串对象:" + (str1 == str2));

//true

其他字符串产生方式:

还有各种其他方式产生的字符串:

字符串常量(final)、静态字符串(static)、字符串相加、字符串对象相加、未引用的字符串、方法中的字符串等

final String str3 = "abc";
System.out.println("字符串与字符串常量:" + (str1 == str3));

//true
System.out.println("未引用字符串相加与常量:" + ("ab" + "c" == str3));

//true
System.out.println("未引用字符串与字符串常量:" + ("abc" == str3));

//true
System.out.println("未引用字符串与引用字符串:" + ("abc" == str1));

//true
static final String str4 = "abc";	//类中定义

System.out.println("未引用字符串与静态字符串:" + ("abc" == str4));	//main中对比

//true
void returnAbc(){
	String str5 = "abc";
	System.out.println("方法中的字符串与静态字符串:" + (str5 == str4));
}

还有个特殊的,字符串对象相加:

String ab = new String("ab");
String c = new String("c");
String abc = ab + c;
System.out.println("对象相加与字符串:" + (abc == str1));
System.out.println("对象相加与对象:" + (abc == str2));

//false
//false

可以看到,相加之后的对象与在常量池中的str1地址不同,所以他也是个字符串对象。

前面说到,字符串对象的地址都是不同的,因此跟另一个字符串对象str2对比结果也是false。

如果让相加产生的字符串对象也调用intern方法,再与intern后的str2对比:

abc = abc.intern();
System.out.println("intern后的两个对象:" + (str2 == abc));

//true

得出结论:

字符串常量存储在堆的常量池中,字符串对象存储在堆的非常量池中

除了字符串对象之外,其他字符串都存储在常量池中。

字符串对象相加产生另一个字符串对象。

结果图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值