Java堆、栈、常量池、String

● 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
● 堆:存放所有new出来的对象。
● 常量池:存放字符串常量和基本类型常量(public static final)。

字符串常量池既不在堆中也不在栈中,是独立的内存空间管理(方法区中)。

对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等(仅仅是值相等)的字符串,在常量池中永远只有一份,在堆中有多份。

String创建对象的两种方式
(1) String str = "abc";
    创建对象的过程:
    ① 首先在常量池中查找是否存在内容为"abc"字符串对象
    ② 如果不存在则在常量池中创建"abc",并让str引用该对象
    ③ 如果存在则直接让str引用该对象
(2) String str = new String("abc");
    创建实例的过程:
    ① 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
    ② 在字符串常量池中查看,是否存在内容为"abc"字符串对象
    ③ 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
    ④ 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来

    intern() 方法可以返回该字符串在常量池中的对象的引用

代码测试:
public class StringTest {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ab";
        String s3 = "c";
        String s4 = "ab" + "c";
        String s5 = s2 + s3;
        String s6 = new String("abc");
        String s7 = s6.intern();

        System.out.println(s1 == s4); // ①
        System.out.println(s1 == s5); // ②
        System.out.println(s1 == s6); // ③
        System.out.println(s1 == s7); // ④
        System.out.println(s6 == s7); // ⑤
    }
}
结果分析:
① true
    因为String s4 = "ab" + "c";会先查找常量池中是否存在内容为"abc"的字符串对象,若存在则直接让s4引用该对象,显然String s1 = "abc";会在常量池中创建"abc"对象,所以s1引用该对象,s4也引用该对象,所以S1 == S4为true。
② false
    因为String s5 = s2 + s3;涉及到变量的相加,会产生新的对象,其内部实现是先new一个StringBuilder,然后append(s2),append(s3),然后让s5引用toString()返回的对象。(若想了解更多细节,可以查看反编译的代码)。
③ false
    String s1 = "abc";------在常量池中建立一个"abc",s1指向"abc";引用s1存储的是"abc"在常量池的地址。
    String s6 = new String("abc");------在堆上分配内存,引用s6存储的是new String("abc") 在堆上的内存地址。
    还有一点区别是s1在类加载时就完成了初始化,而s6 要在执行引擎执行到那一行代码时才完成初始化。
④ true
    String s7 = s6.intern();中intern 方法返回s6在常量池中的对象的引用,在字符串常量池中查看,是否存在与字符串s6的内容"abc"相等的字符串对象,此处已经存在String s1 = "abc";已经存在内容为"abc"的字符串对象。
⑤ false
    此处String s7 = s6.intern();等同于String s7 = "abc";
    与③同理。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值