通过final变量实现条件编译

首先来比较两段代码所产生的中间代码:

 

public class AppConfig {

    public static final boolean debug = true;

}

public class DebugCode {

    public static void main(String[] args) {

       if(AppConfig.debug) {

           System.out.println("Some debug information");

       }

    }

}

DebugCode的中间代码(部分):

public class org.levin.insidejvm.miscs.DebugCode {

  public static void main(java.lang.String[] args);

    0  getstatic java.lang.System.out : java.io.PrintStream [16]

    3  ldc <String "Some debug information"> [22]

    5  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]

    8  return

}

 

public class AppConfig {

    public static final boolean debug = false;

}

public class ReleaseCode {

    public static void main(String[] args) {

       if(AppConfig.debug) {

           System.out.println("Some debug information");

       }

    }

}

 

ReleaseCode中间代码(部分):

public class org.levin.insidejvm.miscs.ReleaseCode {

  public static void main(java.lang.String[] args);

    0  return

}

 

在上面的代码中,很明显DebugCodeReleaseCode中的代码是一样的,只是AppConfig.debug的值不一样而已,却产生了不同的中间代码,即编译器在AppConfig.debugfalse的时候直接忽略了if中的语句。利用这个特性,我们就可以根据配置来实现条件编译,从而实现不同的条件产生不同的中间代码而不只是不同的运行结果。

 

然而在这里为什么会出现这样的行为呢?

这是因为编译器对final修饰的基本类型和String类型的变量,在编译时解析为一个本地拷贝,这样拷贝导致编译器在编译的时候明确的知道ReleaseCode的那一段if语句是不会被执行的,因而可以对其做优化。而这种替换的结果也使得用final修饰的int变量可以出现在switch-case语句中。

 

这种方式的缺陷

这种方式的缺陷在于要现实该机制的条件编译,在改变AppConfig.debug中的值时,需要同时对AppConfig类和ReleaseCode类进行编译(即不能只编译AppConfig类)。

 

参考:《深入Java虚拟机(第二版)》第八章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值