• String与常量池(JDK1.8)


    ---- 基础知识

        String是final类, 并且其方法都被final修饰

        String通过char数组来保存字符串

        对String对象的任何操作都不会影响到原来的String对象, 所有的改变都会创建新String对象

    ---- 创建与内存场景分析

    ?--- 常量赋值

       代码:

      

      内存图:

     

      分析:对于常量赋值来说, 变量s1始终指向了字符串常量池的字符串(只有一份)

    ?--- new String("xxx");的运行

       代码:

     源代码:

     

    内存图:

     

    分析:

           首先先来考虑一下这一句的执行过程,这句一共生成了两个对象,分别是“abc” 和  new String("abc"),考虑类的加载对一个类只会执行一次,“abc”在类加载的时就已经创建驻留(如果该类加载之前已经有"abc"字符串驻留了,那么不需要重复创建用于驻留的"abc"实例)。驻留的字符串是放在全局共享的字符串常量池中的。

          在这段代码后续被运行的时候,"abc"字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1 持有。所以可以看到“abc” 是存在于常量池中 ,而s1指向堆里的对象。

    ?---常量字符串的拼接(使用+)

       代码:

     

      内存图:

       

     分析:

         当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量, 该字符串是在编译期就能确定。先是在池里生成“a”和“b”,再通过拼接的方式生成"ab"

         若一个String对象被final修饰, 并且形式为final String s = "xxx";可以将之看做是常量

     ?---非常量字符串拼接(使用+)

       代码:

     

      内存图:

      

      分析:

         这句话一共生成了5个对象,首先会先在池子生成“a”和“b”,然后会在堆里生成对象new String("a") 和 new String("b),这两个对象分别指向常量池的所对应的字符串,接着由于“+”的作用下,创建了新的对象,这个对象通过利用之前的对象所指向的字符进行拼接生成“ab”,即这波操作是在堆里实现的,不会将生成的"ab"放在常量池里,此时之前的两个对象已经没有作用了,需要等待垃圾回收。

    ?---小结

      不管是new String("XXX")和直接常量赋值, 都会在字符串常量池创建.只是new String("XXX")方式会在堆中创建一个中转站去指向常量池的对象, 而常量赋值的变量直接赋值给变量

      当使用了变量字符串的拼接(+, sb.append)都只会在堆区创建该字符串对象, 并不会在常量池创建新生成的字符串

    ----String intern()方法

      用法解释:

        当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。 否则,此String对象将添加到池中,并返回对此String对象的引用

    举个栗子

       代码:

     

       内存图:

    分析:

        可以看出,是先在池里创建“a”好后,返回一个对象引用赋给堆里的对象new String("a"),也就s1所指向的地方,在堆里。通过调用 intern() 方法,在池里找到S1对象所对应的字符串,并且进行返回给S2对象,所以S2所指向的地方,在常量池里。

     举个栗子

       代码:

       

        内存图:

        

         分析:由于常量池不存在ba, 所以返回堆区ba的地址并添加到常量池中, s2指向了常量池的inte指针

    ---- 谈谈 “+”

       若+号前后为常量,编译期会处理

       若+号前后存在着变量,首先以最左边的字符串为参数创建StringBuilder对象,然后依次对右边进行append操作,最后将StringBuilder对象通过toString()方法转换成String对象

     参考资料: https://blog.csdn.net/qq_26222859/article/details/73135660#commentBox

  • 相关阅读:
    通知协议KVO的用法
    UIImageView用法
    默默的学习!
    多输入参数的方法
    一本书的摘录
    实例、局部、静态变量(java)
    分数相加的例题
    类的继承
    多线程
    单例
  • 原文地址:https://www.cnblogs.com/liangyueyuan/p/9796992.html
Copyright © 2020-2023  润新知