是否有一种方法可以在java中定义标志,并仅在这些标志已定义时运行代码?

是否有一种方法可以在java中定义标志,并仅在这些标志已定义时运行代码?,java,Java,在c\c++中可以定义: #ifndef <token> /* code */ #else /* code to include if the token is defined */ #endif #ifndef /*代码*/ #否则 /*如果定义了令牌,则要包含的代码*/ #恩迪夫 我的问题是,有没有一种用java实现的方法?(未定义全局静态变量..) 例如,我只想在调试模式下运行一些代码 谢谢 上面粘贴的剪贴是为预处理器准备的,预处理器在编译之前“转换”源代码

c\c++
中可以定义:

#ifndef <token>
    /* code */
#else
    /* code to include if the token is defined */
#endif
#ifndef
/*代码*/
#否则
/*如果定义了令牌,则要包含的代码*/
#恩迪夫
我的问题是,有没有一种用java实现的方法?(未定义全局静态变量..) 例如,我只想在调试模式下运行一些代码


谢谢

上面粘贴的剪贴是为预处理器准备的,预处理器在编译之前“转换”源代码

Java没有等价的语言结构,因此答案是您不能这样做

编辑:但是您可以使用常规条件来实现您的目标,因为这样编译器将以所需的方式优化字节码(感谢@StephenC指出这一点)

但我个人更喜欢在需要的地方扩展API进行调试,这将隐藏实现细节,并且可以在运行时更改。当然,这是特定于场景的

例如,这类似于Log4j-s,它允许您检查代码是否处于调试模式


我建议使用这种模式,因为这不会破坏(太多:)我们钟爱的面向对象概念。

答案是否定的。不是你的意思

在Java中执行此类操作的方式如下:

private static final boolean flag = true;  /* or false :-) */

if (flag) {
   /* code */
} else {
   /* different code */
}

java没有预处理器(如C和C++)。但是,如果

flag
是编译时常量表达式,编译器将优化掉上述
if
语句中未使用的分支。这是一种有限形式的条件编译。请注意,控制
标志
常量可以从其他类导入

(IIRC,此行为在JLS中指定……这意味着您可以依靠任何符合标准的Java编译器来完成。)


@Treebranch评论说“这”会导致代码膨胀

  • 如果@Treebranch谈论的是对象代码膨胀,那么这是不正确的。如果使用JLS定义的编译时常量表达式的标志/表达式正确执行此操作,则编译器不会为“条件排除”源代码发出任何字节码。见@edalorso的答案

  • 如果@Treebranch谈论的是源代码膨胀,我同意。但是对于
    #ifdef
    条件编译也可以这样说。(宏和
    #include
    可以用来减少源代码膨胀……但这是以可读性、可维护性等为代价的,这也是Java设计人员拒绝支持任何源代码预处理的原因。)

  • Java有更好的方法来处理平台差异、功能变化等:使用动态绑定。如果您的JAR中有很多不同的插件类是一个问题(字节码膨胀),那么可以通过为每个平台创建不同的JAR文件或其他方式来处理它


  • Java中没有什么比条件编译更好的了。(正如xea所说)

    根据你想解决的问题,有很多类似的方法

    一种是使用静态final变量设置为编译时常量(正如Stephen所写)。编译器实际上不会包含不可能路径的字节码。但它仍然必须是合法的java,这意味着您不能在一个这样的块中声明变量并在另一个块中使用它


    我知道到目前为止我所看到的所有案例都可以使用OO构造来解决。例如,您可以通过调用抽象方法替换您的IF,并提供调试和生产实现。

    < P> java作为一种语言,没有类似的预处理或宏,如C或C++,但是,有一些工具,可以处理这些事情。为了方便使用,您需要将它们连接到Maven或Ant构建中。

    我认为@StephenC提出的是一个不错的选择。或者,您可以尝试使用AspectJ编入您想要用于特定实现的代码。当您不希望将方面作为实现的一部分时,您可以简单地删除它(不要在代码中编织)。AspectJ根据您指定的位置类型(称为切入点)修改字节码(编译的Java代码)。这特别适合于将日志添加到程序中


    如果这是一种您感兴趣的方法,请查看:和。

    建议使用最终静态布尔变量的方法与建议的功能最接近,因为编译器甚至对其进行了优化。如果该标志设置为false,则甚至不会生成块中包含的字节码

    让我举一个例子:

    public class Optimized {
    
        private static final boolean DEBUG = true;
    
        public static void main(String[] args) {
            if(DEBUG){
                System.out.println("DEBUG enabled");
            }
        }
    
    }
    
    这将生成字节码

    public class Optimized {
      public Optimized();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           3: ldc           #3                  // String DEBUG enabled
           5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
           8: return
    }
    
    字节码如下所示

    public class Optimized {
      public Optimized();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: return
    }
    
    公共类优化{
    公共优化();
    代码:
    0:aload_0
    1:invokespecial#1//方法java/lang/Object。“:()V
    4:返回
    公共静态void main(java.lang.String[]);
    代码:
    0:返回
    }
    

    因此,好吧,这是最接近Java中的预编译指令。

    OP问“有没有一种方法可以在Java中实现它?(它没有定义全局静态变量…)”Java没有全局变量。。。从技术上说,Read是不成熟的。可以说,<代码>静态最终< /COD>字段等同于全局变量,例如C++(至少从使用角度来看)…但是你的解释是通过OP的接受来确认的,所以你也得到了我的+1:-p)@ Pyt Tort Rok。静态的最终字段不是全局的,因为在C、C++和FORTRAN中变量可以是全局的。它们必须用类名限定,即使这样,它们也不一定可见。除此之外,我的回答是“不-不是你的意思”。“你可以使用常规条件来实现你的目标,但这不会影响构建过程,这取决于你的令牌。”-严格来说不是真的。如果情况
    public class Optimized {
      public Optimized();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: return
    }