Java中的#ifdef #ifndef

jut*_*tky 103 java conditional compilation conditional-compilation

我怀疑是否有一种方法可以在Java中创建编译时条件,如C++中的#ifdef #ifndef.

我的问题是有一个用Java编写的算法,我有不同的运行时间改进了该算法.所以我想测量每次改进时我节省了多少时间.

现在我有一组布尔变量,用于在运行时决定应该使用哪些改进,哪些不使用.但即使测试这些变量也会影响总运行时间.

所以我想找到一种方法来在编译期间决定编译和使用程序的哪些部分.

有人知道在Java中使用它的方法.或者也许有人知道没有这样的方式(它也会有用).

Mar*_*ton 122

private static final boolean enableFast = false;

// ...
if (enableFast) {
  // This is removed at compile time
}
Run Code Online (Sandbox Code Playgroud)

如上所示的条件在编译时进行评估.相反,如果你使用它

private static final boolean enableFast = "true".equals(System.getProperty("fast"));
Run Code Online (Sandbox Code Playgroud)

然后,任何依赖于enableFast的条件都将由JIT编译器进行评估.这个开销可以忽略不计.

  • IIRC,这在Java拥有JIT编译器之前甚至有效.我认为`javac`删除了代码.这只有在(例如)`enableFast`的表达式是编译时常量表达式时才有效. (6认同)
  • @tomwhipple:true,加上这不允许你做类似的事情:`private void foo(#ifdef DEBUG DebugClass obj #else ReleaseClass obj #endif) (3认同)
  • 那么进口呢(例如,关于类路径)? (3认同)
  • 是的,但是这个条件必须位于一个方法中,对吗?那么我们想要设置一堆私有静态最终字符串的情况呢?(例如,为生产与登台设置不同的一组服务器URL) (2认同)

Phi*_*oss 43

javac不会输出无法访问的编译代码.使用最终变量设置为您的常量值#define和.的正常if语句#ifdef.

您可以使用javap来证明输出类文件中不包含无法访问的代码.例如,请考虑以下代码:

public class Test
{
   private static final boolean debug = false;

   public static void main(String[] args)
   {
       if (debug) 
       {
           System.out.println("debug was enabled");
       }
       else
       {
           System.out.println("debug was not enabled");
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

javap -c Test 给出以下输出,表明只编译了两个路径中的一个(并且if语句不是):

public static void main(java.lang.String[]);
  Code:
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #3; //String debug was not enabled
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
Run Code Online (Sandbox Code Playgroud)

  • 这个javac是特定的,还是这个行为实际上是由JLS保证的? (2认同)
  • 顺便说一下,这个答案应该是公认的答案. (2认同)

jut*_*tky 11

我认为我已经找到了解决方案,它更加简单.
如果我使用"final"修饰符定义布尔变量,Java编译器本身就可以解决问题.因为它事先知道测试这种情况的结果是什么.例如这段代码:

    boolean flag1 = true;
    boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }
Run Code Online (Sandbox Code Playgroud)

在我的电脑上运行大约3秒钟.
还有这个

    final boolean flag1 = true;
    final boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }
Run Code Online (Sandbox Code Playgroud)

跑了大约1秒钟.这段代码需要同样的时间

    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }
Run Code Online (Sandbox Code Playgroud)