在 java 中并不完全支持 DEBUG/RELEASE。但是有一些事实需要记住,还有一些其他方法可以完成同一件事。
Java 的创建者认为,无论外部因素如何,让每个编译单元生成完全相同的字节码是非常有利的,因此 Java 没有预处理器。
Java 与您熟悉的那种 DEBUG/RELEASE 最接近的是 assert 关键字。您可以通过向 VM 提供-assertionsenabled(简称-ea)参数来控制是否评估断言。阅读它,并阅读如何将参数传递给 VM。
注意VM参数是运行时参数,它们与编译器无关,这意味着断言总是由编译器发出到字节码中,如果你不提供-ea,那么运行时将抑制从评估他们。因此,至少仍然会为每个断言执行隐藏的 if( assertionsEnabled ) { ... } 语句。
另一件值得记住的事情是public static final 变量被视为编译时常量,并且编译器可以避免为if( false ) 子句控制的源代码发出任何字节码。但是,源代码总是会被编译,所以它必须是正确的,尽管不会生成字节码。
因此,您可以定义一个全局变量public static final boolean DEBUG = true 来控制所有调试代码,但是您必须在源代码中手动更改它并重新构建您的项目才能生成发布版本; java 特别避免提供任何其他方式来实现这一点。
另外,请注意if( false )(以及扩展名if( DEBUG ))会产生关于条件始终为真或始终为假的警告,所以我不喜欢使用它。
Java 的理念是,我们通常不关心性能到如此偏执的程度,以至于想要完全控制 DEBUG 和 RELEASE 之间微小的性能差异。一般来说,assert 关键字就足够了,实际上(令我沮丧的是)大多数 java 人甚至不使用 assert 由于各种(蹩脚,恕我直言)原因。
至于发出调试信息,无论如何,绝大多数调试信息都是生成的,因为它必须在运行时通过反射可用。我知道您可以控制一件小事:-parameters 编译器选项,但它确实无关紧要,未来版本的编译器可能会弃用该选项并包含它控制的功能标准行为。
这也意味着 java 代码可以比 C++ 代码更容易地进行逆向工程,因此存在 java 混淆器,它们在将代码发送到 java 编译器之前通过标识符处理阶段,以便减少字节码文件中有用信息的数量。
您可能很高兴知道,由于 JITting,这一切都还不错:字节码由 VM 编译成机器码,并且在该阶段执行了许多优化,因此您始终可以从中受益,而不仅仅是发布。
至于检测断言是否开启,可以使用如下代码:
static boolean areAssertionsEnabled()
{
//noinspection UnusedAssignment
boolean b = false;
//noinspection ConstantConditions,AssertWithSideEffects
assert b = true;
//noinspection ConstantConditions
return b;
}
noinspection 的东西用于抑制 IntelliJ IDEA 中的警告,这是一个远远优于 Eclipse 的 Java IDE。如果您坚持使用 Eclipse,您将不得不为它找到等效的警告抑制机制。