`
ruilin215
  • 浏览: 1143368 次
  • 性别: Icon_minigender_2
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

通过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类)。

 

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

3
6
分享到:
评论
2 楼 神之小丑 2011-07-26  
看JDK7,nio2里的 Pool.java有这一段:
    private void d(String msg, int i) {
        if (debug) {
            System.err.println(this + "." + msg + i);
        }
    }

    private void d(String msg, Object obj) {
        if (debug) {
            System.err.println(this + "." + msg + obj);
        }
    }

public final class LdapPoolManager {
。。。
    public static final boolean debug =
        "all".equalsIgnoreCase(getProperty(DEBUG, null));
。。。
}

刚开始不懂为撒要 if(debug),这里是不是 就是条件编译这样的意思啊
1 楼 Coding.Ghost 2011-07-26  
beautiful...you are a programer?

相关推荐

    java final变量详解

    Java final 变量详解 Java 中的 final 变量是指不能被改变的变量,它有三个方面的作用:修饰变量、修饰方法和修饰类。在 Java 中,final 变量是一种常量,它只能被赋值一次,赋值后值不再改变。 final 变量的使用...

    2021-2022年收藏的精品资料软件工程师Java如何实现条件编译教程方法.docx

    总结来说,Java中的条件编译是通过利用编译器的优化功能,结合`final`常量和静态类来实现的。这种技术虽然不如C或C++中的预处理指令直接,但仍然可以有效地帮助我们在开发过程中实现代码的有条件执行,从而提高代码...

    final变量.

    `final`关键字有时用于效率考虑,特别是当一个方法被认为是最佳实现时,不希望用户通过覆盖方法来改变其行为。例如,JDK中的某些方法被声明为`final`,以防止用户意外或故意地影响JVM或系统的性能。 2. **设计需求...

    深入理解final变量的初始化

    这使得`final`变量成为实现线程安全的常用工具。 总结来说,`final`变量的初始化必须在定义时、构造函数中或者初始化代码块中进行,并且要遵循特定的顺序和规则。理解这些规则对于编写健壮和可靠的Java代码至关重要...

    java_中的_final_变量[文].pdf

    而`final`方法由于不能被覆盖,所以在编译时就可以确定调用的具体实现,从而可以进行内联优化,提高性能。 在实际应用中,`final`关键字常见于以下几个场景: 1. `final + 变量`:在某些特定情况下,如日志记录器...

    Java中final的深度剖析

    同时,final变量的编译时替换也有助于提高代码执行速度。 6. **final和异常处理** 在异常处理中,final关键字也有其作用。当在catch块中捕获到异常后,可以声明一个final变量来存储该异常,确保在后续的finally块...

    ClassFinal-java class文件安全加密工具

    2. **混淆**:混淆是另一种保护代码的方法,它通过重命名类、方法和变量,以及改变控制流结构,使得反编译后的代码变得难以理解和分析。ClassFinal可能包含多种混淆策略,如名称混淆、控制流混淆、字符串加密等。 3...

    Java 多线程与并发(6-26)-关键字- final详解.pdf

    final的实现原理是通过在编译期和运行期的特殊处理来实现的。在编译期,final域被编译器特殊处理,使其在编译期就被确定下来。在运行期,final域的访问顺序是按照final域的定义顺序。 四、使用final的限制条件和...

    关于Java中final的深度剖析.pdf

    final变量可以在编译时被初始化,也可以在运行时被初始化,但是一旦被初始化,final变量的值就不能被修改了。使用final变量可以提高代码的可读性和可维护性,因为它可以避免不必要的逻辑错误。 例如,在数学计算中...

    Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释.doc

    - 访问`b`时编译成功并正确输出,因为`b`是final变量。 3. **JVM的行为**: - 对于`b`,JVM会在`Inner`类中创建一个隐式的final变量副本。 - 这个副本是`b`的精确复制,并且可以在`Inner`类的任何地方被访问。 ...

    深入理解Java中的final关键字_动力节点Java学院整理

    6. 未初始化的 `final` 变量被称为“空白 final 变量”,在编译时必须赋值。 了解这些 `final` 关键字的知识点对于编写高效、安全的 Java 代码至关重要,特别是在设计不可变类和保证代码行为不变性时。通过正确使用...

    【Java编程教程】详解Java final 关键字.pdf

    // 编译错误,不能修改final变量 } ``` ### 空白或未初始化的最终变量 如果`final`变量在声明时没有赋值,那么它被称为“空白最终变量”或“未初始化的final变量”。这样的变量必须在构造函数中进行初始化,或者...

    final关键字和static_用法

    // 编译错误, final变量的值一旦给定就无法改变 // t.D = 71; // 编译错误, final变量的值一旦给定就无法改变 System.out.println(t.A); System.out.println(t.B); System.out.println(t.C); // 不推荐用对象...

    Java中final作用于变量、参数、方法及类该如何处理

    尝试修改`final`变量的值会导致编译错误。例如: ```java final int VALUE_ONE = 10; VALUE_ONE = 20; // 编译错误,无法重新赋值 ``` - **final引用类型变量**:对于引用类型的变量,`final`保证了引用本身的不可...

    java成员变量覆盖问题

    如果两个变量之间存在重写关系,那么在同一作用域内定义相同的`final`变量将会导致编译错误。下面是修改后的代码: ```java public class Test1 { final String color = "黄色"; public void getMes() { System....

    Java final关键字

    在Java编程语言中,`final`关键字扮演着一个至关重要的角色...通过合理使用`final`,我们可以提高代码的可读性、可维护性和安全性。在实际开发中,应根据需求灵活运用`final`关键字,以实现更清晰、更稳定的代码设计。

    编译原理final.zip

    编译原理是计算机科学中的一个...学习和理解编译原理不仅有助于深入理解计算机的工作原理,还能为编程语言设计、编译器实现、甚至软件性能优化提供坚实的基础。对于计算机专业的学生来说,掌握编译原理是至关重要的。

    java中final关键字和static关键字详细用法

    同时,`final`方法在编译时会被优化,提高执行效率。 对于变量,`final`修饰的变量称为常量,一旦被赋值后,其值不能更改。`final`变量可以是类级别的(静态`static`)或实例级别的。静态`final`变量通常作为类级别...

Global site tag (gtag.js) - Google Analytics