关于常量表达式

反射那些事反射这篇文章有谈到一个常量表达式的问题,想单独拿出来研究一下。

private final int INT_VALUE=12;//常量表达式
if(a>INT_VALUE){
    //todo
}

那么java编译器会对常量表达式进行一个优化,变成如下:

if(a>12){
    //todo
}

简单举个例子,上面例子没有太直观。

public class ConstantTest {

    private final int a=12; //常量表达式

    private int b=12; //普通成员变量

    private final boolean flag=null==null?true:null; //非常量表达式

    public void solve(int b){
        if(b>a){
            System.out.println("yep");
        }
    }

    public void solve(){
        if(flag){
            System.out.println(b);
        }
    }

    public static void main(String[] args) {
        ConstantTest test=new ConstantTest();
        test.solve(13);
        test.solve();
    }

}

我们对ConstantTest.class文件进行反编译看看:

package com.reflect;

import java.io.PrintStream;

public class ConstantTest {
    private final int a = 12;
    private int b = 12;
    private final boolean flag = null == null ? Boolean.valueOf(true) : null;

    public void solve(int b) {
        if (b > 12) { //这里我们看到了编译器直接进行了优化,把a直接用12来进行替代。
            System.out.println("yep");
        }
    }

    public void solve() {
        if (this.flag) { //非常量表达式和普通成员变量没有发生变化
            System.out.println(this.b);
        }
    }

    public static void main(String[] args) {
        ConstantTest test = new ConstantTest();
        test.solve(13);
        test.solve();
    }

举一些例子符合常量表达式和不符合常量表达式的例子:

public class ConstantTest {

    private final int x=2; //yes
    private final int y=x+2;//yes 常量传播
    private final int f;//no 没有被初始化
    private final int z= Integer.valueOf("42");//no 不是常量表达式

    public ConstantTest() {
        this.f=2;
    }

    public static int t(){
        final int x=2;
        int y=new int[2].length;
        return x+y;
    }

    public static int s(){
        return 12*18-12+30; //会进行常量折叠
    }

    public void test(){
        System.out.println(x+" "+y+" "+f+" "+z);
    }

}

反编译结果:

package com.reflect;
import java.io.PrintStream;
public class ConstantTest {
   
    private final int x = 2;
    private final int y = 4;
    private final int f = 2;
    private final int z = Integer.valueOf("42");

    public static int t() { 
        int x = 2;
        int y = new int[2].length;
        return 2 + y;
    } //向这里有人说是可以直接被优化成
    
    public static int t() { 
        return 4; //可是我的ide并没有 估计其他是可以的
    }

    public static int s() {
        return 234; //上面复杂的常量运算被优化成最终的计算结果
    }

    public void test() {
        System.out.println("2 4 " + this.f + " " + this.z);
    }

}

关于常量的优化:
总共有三种方式:

  • 常量折叠:把常量表达式的值求出来作为常量嵌在最终生成的代码中,这种优化叫做常量折叠(constant folding)。
  • 常量传播
  • 条件常量传播
    以后再慢慢了解吧。

参考: 对于一个很复杂的常量表达式,编译器会算出结果再编译吗?
参考: Chapter 15. Expressions

posted on 2018-10-14 18:59  小新动感光波  阅读(415)  评论(0编辑  收藏  举报

导航