java关于String的编译优化

   public static String getA() {
        return "a";
    }

    public static void main(String[] args) {
        String a = "a";
        final String c = "a";

        String b = a + "b";
        String d = c + "b";
        String e = getA() + "b";

        String compare = "ab";

        System.out.println(b == compare);
        System.out.println(d == compare);
        System.out.println(e == compare);
    }

输出:

false
true
false

编译器优化是有选择的,其实只要记住一句话就行了:只有编译阶段能确定的值,编译器才可以进行优化
我们回过头来看上面的代码,a是一个局部变量,后期还可能会被赋值,编译器不确定它的值,所以不会对b的值进行优化,所以此时在进行+运算给b赋值的时候被编译为下面的语句:

StringBuilder temp = new StringBuilder();
temp.append(a).append("b");
String b = temp.toString();

第二个输出为true,是因为增加了一个final声明,从而强制约束c是不可以改变的,编译器知道c不可改变,所以自然将d的赋值过程优化,指向静态区ab的地址;

第三个输出为false,同样的道理,getA()返回一个常量的引用,但是编译器并不能确切知道函数返回的值是什么,否则需要将函数执行一遍,所以这部分没有进行优化,结果应该为false

intern

String a = "a";
String b = a + "b";
String c  = "ab";
String d = new String(b);

System.out.println(b == c);
System.out.println(c == d);
System.out.println(c == d.intern());
System.out.println(b.intern() == d.intern());
false
false
true
true

看到上面的结果感到意外吗?其实熟悉了intern的用法就会明白。
运行时常量池相对于CLass文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入CLass文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用比较多的就是String类的intern()方法.
String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,434评论 0 9
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我们天天就是要...
    二毛_coder阅读 520评论 1 1
  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 16,024评论 3 83
  • String 类可以认为是 Java 语言中最为常用的类了,对于 String 的理解更是 Java 面试题的常客...
    Kerwong阅读 1,837评论 0 3
  • 美好意外--经典的经典音乐 每天早上,经典的经典音乐是我上班路上美好的享受之一。慢慢地,我觉得光自己享受不够,要让...
    近馨阅读 360评论 8 8

友情链接更多精彩内容