String:字符串常量池详解

本文基于jdk8

使用双引号声明的字符串
使用双引号声明的字符串,先在常量池中查找。如果有相同的,就直接把引用返回;否则就在常量池中创建并返回引用

        //因为用双引号声明的String对象会直接放在常量池中。
        String s1 = "abc";//常量池中的引用
        String s2 = "abc";//常量池中的引用
        //使用双引号声明的字符串,先在常量池中查找,
        //如果有相同的,就直接把引用返回,如果没有就在常量池中创建并返回引用
        System.out.println(s1 == s2);//true

使用new关键字创建的字符串
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有该字符串,如果有则在堆中创建对象返回堆中的引用;如果常量池中没有该字符串则先在常量池中创建字符串,之后在在堆中创建字符串对象,并返回堆中的引用

        //采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"xyz"这个字符串对象,
        // 如果有,则不在池中再去创建"xyz"这个对象了,直接在堆中创建一个"xyz"字符串对象,
        // 然后将堆中的这个"xyz"对象的地址返回赋给引用s3,
        // 这样,s3就指向了堆中创建的这个"xyz"字符串对象;
        
        // 如果没有,则首先在字符串池中创建一个"xyz"字符串对象,然后再在堆中创建一个"xyz"字符串对象,
        // 然后将堆中这个"xyz"字符串对象的地址返回赋给s3引用,
        
        // 这样,s3指向了堆中创建的这个"xyz"字符串对象。s4则指向了堆中创建的另一个"xyz"字符串对象。
        // s3 、s4是两个指向不同对象的引用,结果当然是false
        String s3 = new String("xyz");//在常量池中创建xyz,在堆中创建对象并返回引用
        String s4 = new String("xyz");//在堆中创建对象并返回引用
        System.out.println(s3 == s4);//false

s.intern()的作用
如果常量池中没有该字符串,调用了该方法,会将常量池中开辟空间,里面保存堆中字符串的地址

{

 

        //在常量池中创建“1”字符串,并且在堆中创建字符串1对象,s1是堆中的引用
        String s1 = new String("1");
        String s3 = s1.intern(); //s3是常量池中的引用
        String s2 = "1"; //s2是常量池中的引用
        System.out.println(s1 == s2);//false
        System.out.println(s2 == s3);//true
        System.out.println(s1 == s3);//false

        //第二种情况
        // 第一个new String("1")先在常量池中创建“1”,在堆中创建“1”对象。
        // 第二个new String("1")因为常量池中已经有“1”了,常量池中就不创建了,在堆中创建“1”;
        // 因为用加号连接了所以在堆中还要创建“11”对象,s3是堆中的11对象
        String s3 = new String("1") + new String("1"); 
        
    
        // 常量池中没有11,先创建(并不是创建“11”,而是存储堆中的引用)再返回常量池中的引用。
        String s5 = s3.intern();
        String s4 = "11";//直接返回常量池的引用
        System.out.println(s3 == s4);//true



		// s3指向的是堆中的11对象
        String s3 = new String("1") + new String("1");
		// s5指向的常量池中的地址,该地址存的是堆中11对象的引用,
        String s5 = s3.intern();
        // s4指向常量池中的地址
        String s4 = "11";
        // 因为常量池的保存的是堆中的引用,三个变量指向是一样的
        System.out.println(s5 == s3);//true
        System.out.println(s5 == s4);//true
       System.out.println(s3 == s4);//true

       System.out.println("======================");

//        String s6 = new String("go") +new String("od");
//        String s7 = s6.intern();
//        String s8 = "good";
//        System.out.println(s6 == s7);//true
//        System.out.println(s7 == s8);//true
//        System.out.println(s6 == s8);//true

        String s1 = "Hello";//直接在常量池中创建“hello”
        //现在常量池中创建He,之后再堆中创建He
        //之后在常量池中创建llo
        //因为常量池中已经有hello了,所以不再常量池中创建了,直接在堆中创建hello;
        String s2 = new StringBuffer("He").append("llo").toString();
        String s3 = s2.intern();//返回常量池中的引用。
    
        System.out.println("s1 == s2? " + (s1 == s2));//false
       System.out.println("s1 == s3? " + (s1 == s3));//true


        String m = "hello,world";
        String n = "hello,world";
        String u = new String(m);
        String v = new String("hello,world");
        System.out.println(m == u); //false m是常量池中的,u是堆中的,并不相等
        System.out.println(u == v); //false u,v是堆中的不同对象,并不相等

        // 发现原来是在JVM启动的时候调用了一些方法,在常量池中已经生成了"java"字符串常量,
//        String s2 = new String("ja") + new String("va");
//        String s3 =  s2.intern();
//        String s4 = "java";
//        System.out.println(s2 == s3);//false
//        System.out.println(s3 == s4);//true


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值