Java String的存储

Java String的存储

String的存储

原理

① Java 将字符串常量实现为 String 对象,编译时期能够确定的字符串常量存储在常量区中:

String a = "12345";	// 编译时期在常量池创建 “123456”,运行时将引用赋值给a
String b = a;		// 运行时将a的引用赋值给b

请添加图片描述

② 运行时才能确定的字符串常量是在堆中创建的:

// 编译时将在常量池创建两个 String 对象 "12345" 和 "67"
String a = "12345";
String a = a.concat("67");		  // 运行时在堆中创建 ”1234567“,并将引用赋值给a
String b = new String("1234567"); // 运行时在堆中创建 ”1234567“,并将引用赋值给b

请添加图片描述

③ 编译时能够合并的字符串常量将会合并、并在常量区中创建,带变量的将无法合并,将在堆中创建:

String a = "12" + "34";	// 编译时在常量区创建 "1234",运行时将引用赋值给a
String b = "";
String c = "67" + b + "89"; // 编译时将在常量区创建 "67" 和 "89",运行时在堆中创建 "6789",并将引用赋值给 c

请添加图片描述

举例

String a = "a";
String b = "b";
String c = "a";
String ab1 = a + b;
String ab2 = "ab";
String ab3 = a.concat(b);
String ab4 = a + b;
String ab5 = "a" + "b";
System.out.println(a == c);			// true
System.out.println(ab1 == ab2);		// false;
System.out.println(ab1 == ab3);		// false;
System.out.println(ab1 == ab4);		// false;
System.out.println(ab1 == ab5);		// false;
System.out.println(ab2 == ab3);		// false;
System.out.println(ab2 == ab4);		// false;
System.out.println(ab2 == ab5);		// true;
System.out.println(ab3 == ab4);		// false;
System.out.println(ab3 == ab5);		// false;
System.out.println(ab4 == ab5);		// false;

请添加图片描述

Intern() 方法

原理

① 对某个 String 变量调用 .intern() 方法:

  • 如果常量池中不存在这个字符串,则:并返回常量池中该子串引用
    • JDK1.6:将字符串构建的对象加入常量池
    • JDK1.7+:将这个对象的引用加入常量池

② 当某个字符串需要被重复使用时,可以考虑使用 inter() ,节省大量重复字符串对象消耗的堆内存(像上一节的举例一样,ab1ab3ab4 的内容一样,但是却占用了不同的堆内存)

注意:后边的举例都以 JDK1.7+ 作为默认环境

举例

例一

(1)String str = new String("abc"); 创建了几个对象?

答:常量池有 “abc” 的话就创建了一个对象,常量池没有 “abc” 的话就创建了两个对象

(2)String str = "abc"; 创建了几个对象?

答:常量池有 “abc” 的话就创建了零个对象,常量池没有 “abc” 的话就创建了一个对象

(3)new String("abc").intern(); 创建了几个对象?

答:常量池有 “abc” 的话就创建了一个对象,常量池没有 “abc” 的话就创建了两个对象

例二
String b = new String("ab" + "cd");
String c = b.intern();
System.out.println(c == b);	// false

由于 "ab" + "cd" 可以合并,因此常量区中刚开始就有 "abcd"b.intern() 没有做什么动作;

请添加图片描述

String a == "";
String b = new String("ab" + a + "cd");
String c = b.intern();
System.out.println(c == b);	// true

由于 "ab" + a + "cd" 无法合并,因此常量区中刚开始没有 "abcd" ,而是在调用了 b.intern() 之后才有,所以 c 指向的也是堆中的 "abcd"

请添加图片描述

例三
String d = "";
String b = new String("ab" + "cd");
String a = "a" + d + "b";
System.out.println(a == a.intern());	// true

因为 "ab" + "cd" 可以合并,因此常量区中刚开始没有 "ab" ,是在 a.intern() 之后才有的,所以 aa.intern() 指向的是同一个对象

请添加图片描述

String d = "";
String b = new String("ab" + d + "cd");
String a = "a" + d + "b";
System.out.println(a == a.intern());	// false

因为 "ab" + "cd" 不能合并,因此常量区中刚开始就有 "ab"a.intern() 没有做什么动作;所以 a.intern() 指的是原来常量区中的 "ab"

请添加图片描述

总结

没啥好总结的hhhh,有点绕,但是把上面的举的例子都理解了就问题不大

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Air浩瀚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值