通过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

}

 

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

 

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

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

 

这种方式的缺陷

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

时间: 2024-12-22 02:57:32

通过final变量实现条件编译的相关文章

static与final变量

变量 一.illegal forward refrence 前天写一个类时遇到一个很眼生的编译错误(问题简化后): punlic final class Constants{   public static int VAR2 = VAR1 + 1;   public static int VAR1 = 1; } 编译时出错(第2行): illegal forward refrence 仔细一想,是因为VAR2引用的VAR1在VAR2之后定义,看来在Java中定义static变量时应遵循"声明先于

java中final 变量作为方法的参数?怎么理解?见下面代码

问题描述 java中final 变量作为方法的参数?怎么理解?见下面代码 class NiMingLei { public static void main(String[] args) { Outer out= new Outer(); out.function(7); out.function(8); } } class Outer { static int y=4; void function(final int a) { class Inter { void method() { Sys

java 中的 final 变量

http://wenjiesu.iteye.com/blog/799332 [java中为什么会有final变量]:     final这个关键字的含义是"这是无法改变的"或者"终态的":     那么为什么要阻止改变呢?     java语言的发明者可能由于两个目的而阻止改变:     1).效率问题:         jdk中的某些类的某些方法,是不允许被用户覆盖的,设计者可能认为,所用方法已经是最好的方法,         用户私自覆盖,或是由于疏忽而覆盖,就

深入理解final变量的初始化_java

final变量的初始化位置 一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中.而且在Java1.1以前,只能是在定义时给值.三是在初如化代码块中{} 或者 static{} 复制代码 代码如下: public class InitOrder {    {        System.out.println("before---field");        //System.out.println("d1="+d1);        d1

Java中final变量使用总结_java

final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值. 通常final定义的变量为常量.如: 复制代码 代码如下: final double PI = 3.14;  当在程序中使用PI这个常量时,它的值就是3.14,如在程序中再次对定义为final的常量赋值,编译器将不能接受: final关键字定义的变量必须在声明时对其进行赋值操作.final除了可以修饰基本数据类型的常量,还可以修饰对象引用.由于数组也可以被用作一个对象引用,所以final可以修饰数组.一旦一个对象引用被

如何在构造器中对可能出现异常的final变量初始化

问题描述 RTpublicclassFinalConstructor(){privatefinalAa;publicFinalConstructor(){//a=getA();}privateAgetA()throwsException(){}} 解决方案 解决方案二:javapuzzlers38题

java-Java 中final修饰的成员变量在创建对象时候会不会被附初值?

问题描述 Java 中final修饰的成员变量在创建对象时候会不会被附初值? 如上所述 Java 中final修饰的成员变量在创建对象时候会不会被附初值? 我看周志明的jvm说在创建对象时候要给所有的内存空间都要初始化为零值(不包括对象头),我就想如果是final类型的会不会被初始化微零值再进行程序员自己编写的赋值语句呢?那样的话是不是就是两次对final变量赋值了? 解决方案 不会自动赋值.不赋值会报错.final修饰成员变量,会强制要求赋上值. 解决方案二: 会,比如int初值就是0 解决方

从思路开始 Java如何实现条件编译

条件编译绝对是一个好东西.如在C或CPP中,可以通过预处理语句来实现条件编译.代码如下: #IFDEF DEBUG  #UNDEF DEBUG  #ENDIF  #define DEBUG  #IFDEF DEBUUG    /*     code block 1     */  #ELSE    /*     code block 2    */  #ENDIF 但是在JAVA中却没有预处理,宏定义这些东西,而有时在一些项目中,我们又需要条件编译.那么,在JAVA中,该如何实现条件编译呢? 我

Java中static、this、super、final用法

一.static  请先看下面这段程序:   public class Hello{     public static void main(String[] args){ //(1)       System.out.println("Hello,world!");   //(2)     }   } 看过这段程序,对于大多数学过Java 的从来说,都不陌生.即使没有学过Java,而学过其它的高级语言,例如C,那你也应该能看懂这段代码的意思.它只是简单的输出"Hello,w