#Java中的ifdef#ifndef 我怀疑在C++中是否有一种编译java时间的方法,比如在C++中的

#Java中的ifdef#ifndef 我怀疑在C++中是否有一种编译java时间的方法,比如在C++中的,java,compilation,conditional,conditional-compilation,Java,Compilation,Conditional,Conditional Compilation,我的问题是,有一个用Java编写的算法,我对该算法有不同的运行时间改进。因此,我想衡量每次改进都能节省多少时间 现在我有一组布尔变量,用于在运行期间决定应该使用哪些改进,哪些不应该。但即使测试这些变量也会影响总运行时间 所以我想找到一种方法,在编译期间决定应该编译和使用程序的哪些部分 有人知道用Java做这件事的方法吗。或者可能有人知道没有这种方法(它也会很有用)。从未使用过它,但它是存在的 JCPP是一个完整的、合规的, 独立的纯Java实现 C预处理器的设计。这是有意的 对写C风格的人有用

我的问题是,有一个用Java编写的算法,我对该算法有不同的运行时间改进。因此,我想衡量每次改进都能节省多少时间

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

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


有人知道用Java做这件事的方法吗。或者可能有人知道没有这种方法(它也会很有用)。

从未使用过它,但它是存在的

JCPP是一个完整的、合规的, 独立的纯Java实现 C预处理器的设计。这是有意的 对写C风格的人有用 使用诸如 sablecc、antlr、JLex、CUP等 向前地该项目已投入使用 要成功地预处理 GNUC库的源代码。作为 在版本1.2.5中,它还可以 对苹果目标进行预处理 图书馆


是否使用工厂模式在类的实现之间切换

对象创建时间现在不成问题了,不是吗?当在长时间运行期间平均时,花费的时间中最大的部分应该在主算法中,不是吗


严格地说,你并不需要一个预处理器来完成你想要实现的事情。当然,除了我提出的方法之外,很可能还有其他方法可以满足您的需求。

javac不会输出无法获得的编译代码。为
#define
使用设置为常量的最终变量,为
#ifdef
使用正常的
if
语句

您可以使用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");
       }
   }
}
javap-c Test
给出以下输出,表明两条路径中只有一条被编译(if语句没有编译):

上面所示的条件是在编译时计算的。如果你用这个

private static final boolean enableFast = "true".equals(System.getProperty("fast"));

然后,JIT编译器将评估任何依赖于enableFast的条件。这方面的开销可以忽略不计。

我想我已经找到了解决方案,它更简单。
如果我用“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++;
    }
boolean flag1=true;
布尔标志2=假;
int j=0;

对于(inti=0;i,如果您确实需要条件编译,并且您使用的是Ant,那么您可能能够筛选代码并在其中进行搜索和替换

例如:

以同样的方式,例如,您可以编写一个过滤器,将
LOG.debug(…);
替换为
/*LOG.debug(…);*/
。这仍然比如果(LOG.isDebugEnabled()){…}
的东西执行得更快,更不用说同时更简洁了

如果您使用Maven,则有一个类似的功能描述

提供了一个完全集成的Java预处理器(无构建步骤或生成的源代码)。它专门针对条件编译,并使用C风格的指令

final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0

如果您使用IntelliJ,有一个名为Manifold的插件,它与许多其他功能一起,允许您在Java中使用
\ifdef
\define

插件url:

预处理器信息:


PS:我与他们没有关系,我们只是碰巧使用了它,而且它在没有工作流的情况下帮助很大(这可能不是Java开发的典型情况)

我不确定这是否适合我的需要。我的代码是用Java编写的。也许你建议我获取他们的源代码,并使用它们来预处理我的代码?更改非常小。比如测试一些条件以提前知道请求的结果,而不是重新计算。因此,调用函数的开销可能不适合我。这是解决方案比我的好。当我尝试用预设的外部值初始化变量时,运行时间回到了3秒。但是当我将变量定义为静态类变量(而不是函数局部变量)时运行时间返回到1秒。感谢help.IIRC,这甚至在Java使用JIT编译器之前就起作用了。我想代码是由
javac
删除的。这只在(比如)的表达式
enableFast
是一个编译时常量表达式。是的,但是这个条件必须驻留在一个方法中,对吗?如果我们有一堆我们想要设置的私有静态最终字符串(例如,一组服务器URL,它们在生产和暂存中的设置不同),情况会怎样@tomwhipple:是的,而且这不允许您执行以下操作:
private void foo(#ifdef DEBUG DebugClass obj#else ReleaseClass obj#endif)
导入如何(例如,关于类路径)?这很有趣。听起来JIT已经支持条件编译了!如果这些最终版本在另一个类或另一个包中,它能工作吗?太好了!那么我相信这一定是一个运行时优化,代码实际上并没有在编译时被剥离。只要你使用一个成熟的VM就行。@Joey Twiddle,关键字是“只要你使用”一个成熟的虚拟机。这是javac特有的,还是JLS确实保证了这种行为?@pacerier,我不知道JLS是否保证了这一点,但我从90年代以来遇到的每一个java编译器都是如此,除了1.1.7之前的可能例外,这只是因为我当时没有测试它。
    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++;
    }
    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++;
    }
    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0