zoukankan      html  css  js  c++  java
  • 关于java字符串编译优化问题

    情景一:不好的字符串拼接习惯   

    起因是这样的:一个大牛在写了一篇关于java字符串优化问题的讲解,他提到:不要使用strObj+otherValue的方法将otherValue转换为字符串形式,因为底层操作会让你吓一跳的。那么底层的实质是怎么样的呢?他的意思是这样的:

     比如:    String s = "I have";

                    int  total = 12;

                    Dog dog = new Dog();     //假设Dog类重写了toString方法

                    String msg = s +  total+dog;

        在运行时,msg的赋值语句会执行为: msg = new StringBuilder().append(s).append(total).append(dog.toString()).toString();

        我们发现,运行时创建了一个匿名的StringBuilder对象,来拼接字符串,存储到缓冲区,最后调用toString方法返回拼接后的结果。显然,StringBuilder在这里小材大用了,而且消耗了内存资源,不可取。我发现很多人都喜欢写类似    ""+num的代码,我也是。所以以后需要注意了,特别是性能敏感的环境下。应该改用String.valueOf(value),或者包装类型的toString方法,比如Double.toString(value)。

     如果需要对字符串进行频繁的修改操作,那就使用StringBuilder,或者StringBuffer(线程安全的),从而避免大量的中间字符串垃圾碎片。    

    情景二:为什么一个是true,一个是false

    一位网友提到了这样一个问题:

    String str = "abc";
    String str1 = "ab" + "c";


    String str2 = "ab";
    String str3 = str2 + "c";  //试试运行这段代码,就会发现第一个为true 第二个为false ,why?

    下面是我的解释:   

          这是因为javac的编译优化造成的。str1是由2个字符串常量拼接的,常量一定是不会改变的量,那么在编译阶段,javac就有胆量将它给简化一下:str1就优化为:str1="abc",又因为str也是"abc",所以str和str1共享了内存据“abc”,所以str和str1都指向"abc"。由于==是浅比较,比较的是字符串的内存地址,所以他们相等。

          而str3的拼接中包含了一个变量str2,而变量是在运行时动态确定的,所以javac不敢再编译时对它优化。也就是说,str3会在运行时在堆中new出字符串对象"abc",显然它的地址和前面的"abc"的地址不一样,所以是false。

    我对上面的程序导出jar后进行反编译,验证了我的猜想,结果如图:

                                                           

     为了进一步证实我的猜想,我把上面的代码改为:

    String str = "abc"; 
    
    final String str2 = "ab"; 
    String str3 = str2 + "c";  
            
    System.out.println(str == str3); //打印出true

         那么问题来了,不是说str2是变量的吗。怎么这次也打印是true呢?注意我给str2加上了修饰符final,声明str2位常量,那么同样的道理,javac也能保证str2不会改变,于是把str3优化为:str3="abc"。

    反编译class文件截图:

                                               

    注意:不要使用 == 去比较字符串,因为字符串时引用类型,== 比较的是内存地址,而不是字符串内容。请使用equals() 或者equalsIgnoreCase()。

              只有字符串常量是共享内存的,而字符串变量或者运行时动态生成的字符串,则非如此。

  • 相关阅读:
    C++ UNREFERENCED_PARAMETER函数的作用
    Win32 Console Application、Win32 Application、MFC三者之间的联系和区别
    解决CSDN博客插入代码出现的问题
    C++ std::vector指定位置插入
    计算机如何与人沟通(1)
    C++ fstream文件操作
    using namespace std 和 include 的区别
    找不到windows.h源文件
    C++ 字符串转换
    WPF style 换肤
  • 原文地址:https://www.cnblogs.com/lulipro/p/5410907.html
Copyright © 2011-2022 走看看