java中String的内存分详解

package 字符串;

/**
 * @author pp
 */

import jdk.swing.interop.SwingInterOpUtils;

/**
 * java中字符串的内存分布问题:
 * 在Java中,通过字符串常量、字量面和String类下的intern()方法创建的字符串都有可能被存储到常量池中。 常量池位于堆之外
 * 但是只要是直接用new创建的String对象那么字符串就会被存在堆区 或者用字符串拼接的方式创建时其中含右用new创建的字符串或者其他包装类型的时候就会在创建在堆区
 * 需要注意的是:虽然一些包装类型在一定范围之内的数据是储存在常量区的,但是利用+和字符串拼接的时候他们会调用toString()方法在堆区创建一个字符串
 * 就算用new创建一个空字符串String s=new s(""); 然后用字面值与他拼接 也会在堆区重新创建一个空间
 *String 中的intern方法是将创建的字符串对象强制加到字符串常量区(如果字符串常量区没有该常量的话)返回的是在字符串常量池中对饮的引用
 */

public class StringMemory {
    public static void main(String[] args) {
        String s1 = new String("123");//最开始的时候常量池中没有"123"字符串存在堆区
        String s2 = "123";//用字面值创建字符串 此时常量池中没有"123" 那么会在常量池中存入"123"
        String s3 = String.valueOf(123);//调用的是包装类型Integer的toString()方法
        String s4 = new String("123");
        String s5 = "123";
        String s6 = "1" + "23";
        String s7 = "" + s1;
        String s8 = String.valueOf(s1);
        String s9 = String.valueOf("123");
        String s10 = "";
        String s11 = new String("");
        String s12=new String("456");
        s12.intern();
        String s13="456";
        System.out.println(s12==s12.intern());//false
        System.out.println(s12==s13);//false
        System.out.println(s12.intern()==s13);//true
        /*
         String s2 = String.valueOf(123);
         这一句其实是调用的如下方法:
          public static String valueOf(int i) {
        return Integer.toString(i);
        }
        -->
        public static String toString(int i) {
        int size = stringSize(i);
        if (COMPACT_STRINGS) {
            byte[] buf = new byte[size];
            getChars(i, size, buf);
            return new String(buf, LATIN1);
        } else {
            byte[] buf = new byte[size * 2];
            StringUTF16.getChars(i, size, buf);
            return new String(buf, UTF16);
        }
    }
    //观察包装类型Integer中重写的toString()方法发先最终使用的关键字new 创建的String对象 所以字符串也是储存在堆区
         */

        /*
          String s8=String.valueOf(s1);
        这句调用的方法如下:
          String s8=String.valueOf(s1);
        String s9=String.valueOf("123");
        -->
        public String toString() {
        return this;
        }
         */

        /*
        String s9 = String.valueOf("123");
        这句调用的方法如下:
          String s8=String.valueOf(s1);
        String s9=String.valueOf("123");
        -->
        String temp="123";
        -->
        public String toString() {
        return this;
        }
         */
        System.out.printf("s1和s2的地址是否相同:%s\ns1和s3的地址是否相同:%s\ns2和s3的地址是否相同:%s" +
                        "\ns1和s4的地址是否相同:%s\ns2和s4的地址是否相同:%s\ns2和s5的地址是否相同:%s\n" +
                        "s2和s6的地址是否相同:%s\ns2和s7的地址是否相同:%s\ns1和s7的地址是否相同:%s\n" +
                        "s1和s8的地址是否相同:%s\ns2和s8的地址是否相同:%s\ns1和s9的地址是否相同:%s\n" +
                        "s2和s9的地址是否相同:%s\ns10和s11的地址是否相同:%s\n"
                , s1 == s2, s1 == s3, s2 == s3, s1 == s4, s2 == s4, s2 == s5,
                s2 == s6, s2 == s7, s1 == s7, s1 == s8, s2 == s8, s1 == s9,
                s2 == s9,s10==s11);


/*运行结果如下:
false
false
true
s1和s2的地址是否相同:false
s1和s3的地址是否相同:false
s2和s3的地址是否相同:false
s1和s4的地址是否相同:false
s2和s4的地址是否相同:false
s2和s5的地址是否相同:true
s2和s6的地址是否相同:true
s2和s7的地址是否相同:false
s1和s7的地址是否相同:false
s1和s8的地址是否相同:true
s2和s8的地址是否相同:false
s1和s9的地址是否相同:false
s2和s9的地址是否相同:true
s10和s11的地址是否相同:false
 */
    }
}

关于常量池:

这里给大家推荐一篇超级超级超级好的文章:

链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

pp不会算法^v^

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

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

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

打赏作者

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

抵扣说明:

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

余额充值