JVM08_字符串常量池基本特性、内存分配、拼接操作、intern、StringTable垃圾回收(二)

简介: ③. 字符串拼接操作④. 拼接操作与append的效率对比

③. 字符串拼接操作


①. 常量与常量的拼接结果在常量池,原理是编译期优化


②. 常量池中不会存在相同内容的常量。


③. 只要其中有一个是变量,结果就在堆中


(只有有一个是变量,那么它会在堆中创建一个StringBuilder,调用append( )方法进行添加操作,调用toString( )方法转换为字符串【toString( )方法其实就是:new String( )】)


④. 如果拼接的结果调用intern()方法分为两种情况:


JDK1.6,将这个字符串对象尝试放入串池 ①. 如果字符串常量池中有,则并不会放入。返回已有的串池中的对象的地址②. 如果没有,它会在常量池中创建一个对象放入串池中,并返回串池中的对象地址


JDK1.7,将这个字符串对象尝试放入串池 ①. 如果字符串常量池中有,则并不会放入。返回已有的串池中的对象的地址②. 如果没有,它不会创建一个对象,如果堆中已经这个字符串,那么会将堆中的引用地址赋给它


test3、test4重点掌握


    @Test
    public void test1(){
        String s1 = "a" + "b" + "c";//编译期优化:等同于"abc" 在字节码文件中,s1="abc"
        String s2 = "abc"; //"abc"一定是放在字符串常量池中,将此地址赋给s2
        /*
         * 最终.java编译成.class,再执行.class
         * String s1 = "abc";
         * String s2 = "abc"
         */
        System.out.println(s1 == s2); //true
        System.out.println(s1.equals(s2)); //true
    }
    @Test
    public void test2(){
        String s1 = "javaEE";
        String s2 = "hadoop";
        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";//编译期优化
        //如果拼接符号的前后出现了变量,则相当于在堆空间中new String(),具体的内容为拼接的结果:javaEEhadoop
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;
        System.out.println(s3 == s4);//true
        System.out.println(s3 == s5);//false
        System.out.println(s3 == s6);//false
        System.out.println(s3 == s7);//false
        System.out.println(s5 == s6);//false
        System.out.println(s5 == s7);//false
        System.out.println(s6 == s7);//false
        //intern():判断字符串常量池中是否存在javaEEhadoop值,如果存在,则返回常量池中javaEEhadoop的地址;
        //如果字符串常量池中不存在javaEEhadoop,则在常量池中加载一份javaEEhadoop,并返回次对象的地址。
        String s8 = s6.intern();
        System.out.println(s3 == s8);//true
    }
    @Test
    public void test3(){
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        /*
        如下的s1 + s2 的执行细节:(变量s是我临时定义的)
        ① StringBuilder s = new StringBuilder();
        ② s.append("a")
        ③ s.append("b")
        ④ s.toString()  --> 约等于 new String("ab")
        补充:在jdk5.0之后使用的是StringBuilder,
        在jdk5.0之前使用的是StringBuffer
         */
        String s4 = s1 + s2;//
        System.out.println(s3 == s4);//false
    }
    /*
    1. 字符串拼接操作不一定使用的是StringBuilder!
       如果拼接符号左右两边都是字符串常量或常量引用,则仍然使用编译期优化,即非StringBuilder的方式。
    2. 针对于final修饰类、方法、基本数据类型、引用数据类型的量的结构时,能使用上final的时候建议使用上。
     */
    @Test
    public void test4(){
        final String s1 = "a";
        final String s2 = "b";
        String s3 = "ab";
        String s4 = s1 + s2;
        System.out.println(s3 == s4);//true
    }
    //练习:
    @Test
    public void test5(){
        String s1 = "javaEEhadoop";
        String s2 = "javaEE";
        String s3 = s2 + "hadoop";
        System.out.println(s1 == s3);//false
        final String s4 = "javaEE";//s4:常量
        String s5 = s4 + "hadoop";
        System.out.println(s1 == s5);//true
    }


image.png


④. 拼接操作与append的效率对比


  • append效率要比字符串拼接高很多


/*
    体会执行效率:通过StringBuilder的append()的方式添加字符串的效率要远高于使用String的字符串
 拼接方式!
    详情:① StringBuilder的append()的方式:自始至终中只创建过一个StringBuilder的对象
           使用String的字符串拼接方式:创建过多个StringBuilder和String的对象
         ② 使用String的字符串拼接方式:内存中由于创建了较多的StringBuilder和String的对象,
           内存占用更大;如果进行GC,需要花费额外的时间。
     改进的空间:在实际开发中,如果基本确定要前前后后添加的字符串长度不高于某个限定值highLevel
     的情况下,建议使用构造器实例化:
     StringBuilder s = new StringBuilder(highLevel);//new char[highLevel]
     */
    @Test
    public void test6(){
        long start = System.currentTimeMillis();
//        method1(100000);//4014
        method2(100000);//7
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为:" + (end - start));
    }
    public void method1(int highLevel){
        String src = "";
        for(int i = 0;i < highLevel;i++){
            src = src + "a";//每次循环都会创建一个StringBuilder、String
        }
//        System.out.println(src);
    }
    public void method2(int highLevel){
        //只需要创建一个StringBuilder
        StringBuilder src = new StringBuilder();
        for (int i = 0; i < highLevel; i++) {
            src.append("a");
        }
//        System.out.println(src);
    }




相关文章
|
1月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
47 6
|
4月前
|
C语言
【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
64 0
|
4月前
|
存储 安全 编译器
【C语言篇】字符和字符串以及内存函数的详细介绍与模拟实现(上篇)
当然可以用scanf和printf输入输出,这里在之前【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)已经讲过了,这里就不再赘述,主要介绍只针对字符的函数.
58 0
|
6月前
|
C语言
字符串和内存函数(1)
字符串和内存函数(1)
60 7
|
6月前
|
算法 Java
垃圾回收机制(Garbage Collection,GC)是Java语言的一个重要特性,它自动管理程序运行过程中不再使用的内存空间。
【6月更文挑战第24天】Java的GC自动回收不再使用的内存,关注堆中的对象。通过标记-清除、复制、压缩和分代等算法识别无用对象。GC分为Minor、Major和Full类型,针对年轻代、老年代或整个堆进行回收。性能优化涉及算法选择和参数调整。
78 3
|
6月前
字符串和内存函数(2)
字符串和内存函数(2)
43 5
|
6月前
|
存储 Python
Python成员属性的内存特性与底层内存优化方案
这篇博客主要分享一下python成员属性的内存特性,也就是python底层节约内存的优化方案
|
6月前
|
算法 安全 Java
JVM系列4-垃圾收集器与内存分配策略(二)
JVM系列4-垃圾收集器与内存分配策略(二)
51 0
JVM系列4-垃圾收集器与内存分配策略(二)
|
5月前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
52 0
|
5月前
|
Java 程序员 C++
C++和Python在内存分配、释放以及垃圾回收机制上有何不同?
【7月更文挑战第2天】C++和Python在内存分配、释放以及垃圾回收机制上有何不同?
60 0