Java常量折叠

常量折叠是Java在编译期间做的一个优化,简单的来说就是在编译期就把一些表达式计算好,不需要在运行时进行计算。

对于如下代码:

String s1 = "a" + "b";
int a = 1 + 3;

java编译器在编译阶段会把值计算出来,也就会变成:

String s1 = "ab";
int a = 4;

对于如下代码(使用javac编译)我们使用Luyten或者JD-GUI打开,可以看到经过优化后的代码:

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

这里写图片描述

所以输出为:
true
false

解释:

String str1 = "ab";
String str2 = "ab";

因为String是不可变的,所以没有必要弄出两个”ab”对象,在内存中(字符串常量池中)只有一个指向”ab”的引用,str1和str2都指向它,所以这里str1==str2应该不难理解。(实际上“ab”还是存在于堆中)
System.out.println(s1 == "ab"); 输出为 true

对于 String s3 = s2 + "b"; 内部实现实际上是创建了一个StringBuilder,然后一直append,最后在toString。
这就是java在String中如何对“+”与“+=”进行运算符重载的实现。

这里写图片描述
(“+”和“+=”是java中仅有的两个运算符重载。)

String s3 = new StringBuilder().append(“a”).append(“b”).toString();

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

它new了一个对象,new出来的东西位于堆上,也就是说s3指向了堆上的一块内存,而s1指向的东东位于常量池,所以使用==会返回false。

进行常量折叠需要满足:
1. 编译时常量(数字字面值,字符串字面值等)。
2. 编译时常量进行简单运算的结果也是编译时常量,如1 + 2,”a”+ “b”。
3. 被 final 修饰的基本类型和字符串变量也是编译时常量。

如:

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

输出也为 true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N3verL4nd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值