java的常量折叠(转载https://www.cnblogs.com/zhenghengbin/p/9683990.html)

英文是 Constant folding, 编译期能确定的值在编译期计算出来,省得运行时浪费资源。
实例解析
昨天,让我迷惑的代码是下面这段代码

public static void main(String[] args) {

    String a = "hello2";
    final String b = "hello";
    String d = "hello";
    String c = b + 2;
    String e = d + 2;
    System.out.println((a == c));
    System.out.println((a == e));

}

这段的执行结果是

true
false
我就是不明白为什么第一个返回true呢?

留着这个疑问,我们先了解下常量折叠的概念。来更好的理解上面的代码

常量折叠
常量折叠的概念
常量折叠是一种编译器优化技术。
常量折叠主要指的是编译期常量加减乘除的运算过程会被折叠
对于 String s1 = “1” + “2”;
编译器会给你优化成 String s1 = “12”;
在生成的字节码中,根本看不到 “1” “2” 这两个东西。

我们通过idea进行验证下

1、源码文件

public static void main(String[] args) {
    String s1 = "1"+"2";
}

2、运行后,idea有个out文件夹,找到上面文件的class文件

public static void main(String[] args) {
    String s1 = "12";
}

确实如上面所说,编译器会给你进行优化

常量折叠发生的条件
必须是编译期常量之间进行运算才会进行常量折叠。
编译期常量就是“编译的时候就可以确定其值的常量”,
首先:字面量是编译期常量。(数字字面量,字符串字面量等)
其次:编译期常量进行简单运算的结果也是编译期常量,如1+2,“a”+“b”。
最后:被编译器常量赋值的 final 的基本类型和字符串变量也是编译期常量。
举个栗子
1.第一个栗子

public static void main(String[] args) {
    String s1="a"+"bc";
    String s2="ab"+"c";
    System.out.println(s1 == s2);
}

相信大家都知道了,输出为true
并且只创建了一个 “abc” 字符串对象,且位于字符串常量池中。

2、第二个栗子

public static void main(String[] args) {
    String a = "a";
    String bc = "bc";
    String s1 = "a" + "bc";
    String s2 = a + bc;
    System.out.println(s1 == s2);
}

这个结果呢?false

s1 是字符串字面量相加,但是 s2 却是两个非 final 的变量相加,所以不会进行常量折叠。

而是根据 String 类特有的 + 运算符重载,变成类似这样的代码 (jdk1.8)

String s2 = new StringBuilder(a).append(b).toString();
这里toString()会生成新的String变量,显然用 == 运算符比较是会返回 false。

3、第三个栗子

public static void main(String[] args) {
    final String a = "a";
    final String bc = "bc";
    String s1 = "a" + "bc";
    String s2 = a + bc;
    System.out.println(s1 == s2);
}

这里的结果就是true

因为 被编译器常量赋值的 final 的基本类型和字符串变量也是编译期常量

4、第四个栗子

public static void main(String[] args) {
    String x ="a";
    final String a = x;
    final String bc = "bc";
    String s1 = "a" + "bc";
    String s2 = a + bc;
    System.out.println(s1 == s2);
}

这里的结果是false

这里需要注意的是:final的变量,不是被编译期常量初始化的也不是编译器常量

这里的a 就不是编译器常量

5、第五个栗子

public static void main(String[] args) {
    String x ="a";
    final String a = x;
    final String bc = "bc";
    String s1 = "a" + "bc";
    String s2 = a + bc;
    System.out.println(s1 == s2.intern());
}

这里的结果是true

其实,这里大家要明白intern这个方法的意思就会明白了

// 一个字符串池,最初是空的,是由类字符串私有维护的。
1、A pool of strings, initially empty, is maintained privately by the class String.

// 如果常量池中已经有了这个字符串,那么直接返回常量池中它的引用,如果没有,那就将它的引用保存一份到字符串常量池,然后直接返回这个引用。
2、When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

3、It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
总结
现在看完,是不是对上面打印的结果为什么是true 知道了呢?
所以。只要牢记常量折叠主要指的是编译期常量加减乘除的运算过程会被折叠

后续补充
上面一开始写的是

而是根据 String 类特有的 + 运算符重载,变成类似这样的代码

String s2 = new StringBuffer(a).append(b).toString();

这里更正下,就是现在我用jdk1.8 通过反编译后先在已经不是StringBuffer 而是StringBuilder。这里需要更正下。我也查询了下。StringBuilder 是jdk1.5之后才有的。

<think>嗯,用户想访问cnblogs上johnnyzen的博客文章,编号是13224632。首先,我需要确认这个博客的具体内容和访问方式。根据用户提供的引用,特别是引用[1],里面提到博客园的系统限制了用户每日更改文章的次数,但客服处理效率高。这可能意味着用户遇到了访问或修改文章的限制,或者想获取被限制访问的内容。 接下来,我需要检查是否有办法直接访问该文章。通常,博客园的文章可以通过URL直接访问,结构通常是https://www.cnblogs.com/用户名/p/文章ID.html。所以用户提供的文章ID是13224632,用户名是johnnyzen,所以完整的URL应该是https://www.cnblogs.com/johnnyzen/p/13224632.html。建议用户直接访问这个链接,看是否能打开。 另外,引用[1]提到每日更改次数限制,如果用户无法访问,可能是因为文章被删除或设置了权限。这时候可能需要联系博客园的客服,如引用[1]所说,他们的处理效率不错。或者,用户可能需要检查网络问题,或者尝试使用缓存页面,比如Google的网页快照。 还要考虑用户是否希望获取技术内容,比如代码或算法。引用[2]和[3]提到了反素数和数据累计算法的内容,可能相关。如果文章涉及这些主题,可以建议用户通过其他途径查找相关资料,比如优快云或使用Paimon维表的数据处理方法,如引用[3]所述。 最后,用户可能需要确保输入的URL正确,没有拼写错误。如果所有方法都失败,建议用户提供更多信息,比如文章标题或内容片段,以便进一步帮助查找。</think>根据您提供的博客文章编号13224632及用户名johnnyzen,该文章的完整访问路径应为: $$https://www.cnblogs.com/johnnyzen/p/13224632.html$$ ### 访问建议步骤: 1. **直接访问链接**:通过浏览器输入上述完整URL访问 2. **搜索引擎缓存**:若原链接失效,可在Google搜索栏输入: ```python cache:https://www.cnblogs.com/johnnyzen/p/13224632.html ``` 3. **联系博客园客服**:引用[1]证实平台存在操作次数限制,但客服响应效率较高 ### 技术内容预判建议: 根据博客园技术博主常涉及领域,该文章可能包含: - 分布式系统设计(参照引用[3]的Paimon维表技术) - 算法实现(参照引用[2]的反素数算法) - 需求分析方法论(参照引用[4]的流程设计策略)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值