Java 中的 #ifdef #ifndef

发布于 2024-08-13 00:49:32 字数 293 浏览 7 评论 0原文

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

我的问题是有一个用 Java 编写的算法,并且我对该算法有不同的运行时间改进。所以我想衡量一下每次使用改进后我节省了多少时间。

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

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

有人知道用 Java 实现这一点的方法吗?或者也许有人知道没有这样的方法(它也很有用)。

I doubt if there is a way to make compile-time conditions in Java like #ifdef #ifndef in C++.

My problem is that have an algorithm written in Java, and I have different running time improves to that algorithm. So I want to measure how much time I save when each improve is used.

Right now I have a set of boolean variables that are used to decide during the running time which improve should be used and which not. But even testing those variables influences the total running time.

So I want to find out a way to decide during the compilation time which parts of the program should be compiled and used.

Does someone knows a way to do it in Java. Or maybe someone knows that there is no such way (it also would be useful).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

橘虞初梦 2024-08-20 00:49:32
private static final boolean enableFast = false;

// ...
if (enableFast) {
  // This is removed at compile time
}

像上面所示的条件是在编译时评估的。如果您使用此选项,

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

则任何依赖于enableFast的条件都将由JIT编译器进行评估。这样做的开销可以忽略不计。

private static final boolean enableFast = false;

// ...
if (enableFast) {
  // This is removed at compile time
}

Conditionals like that shown above are evaluated at compile time. If instead you use this

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

Then any conditions dependent on enableFast will be evaluated by the JIT compiler. The overhead for this is negligible.

无需解释 2024-08-20 00:49:32

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 语句未编译):

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

javac will not output compiled code that is unreachable. Use a final variable set to a constant value for your #define and a normal if statement for the #ifdef.

You can use javap to prove that the unreachable code isn't included in the output class file. For example, consider the following code:

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 gives the following output, indicating that only one of the two paths was compiled in (and the if statement wasn't):

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
百善笑为先 2024-08-20 00:49:32

我想我已经找到了解决方案,它更简单。
如果我使用“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++;
    }

在我的计算机上运行大约 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++;
    }

运行时间大约为 1 秒。此代码花费的时间相同

    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }

I think that I've found the solution, It's much simpler.
If I define the boolean variables with "final" modifier Java compiler itself solves the problem. Because it knows in advance what would be the result of testing this condition.
For example this code:

    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++;
    }

runs about 3 seconds on my computer.
And this one

    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++;
    }

runs about 1 second. The same time this code takes

    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }
烟柳画桥 2024-08-20 00:49:32

没用过,不过这个确实存在

JCPP 是一个完整的、合规的、
独立的、纯 Java 实现
C 预处理器。其目的是
对编写 C 风格的人有用
Java 编译器使用类似的工具
sablecc、antlr、JLex、CUP 等
四。该项目已被使用
成功地预处理了大部分
GNU C 库的源代码。作为
1.2.5版本还可以
预处理 Apple Objective C
图书馆。

http://www.anarres.org/projects/jcpp/

Never used it, but this exists

JCPP is a complete, compliant,
standalone, pure Java implementation
of the C preprocessor. It is intended
to be of use to people writing C-style
compilers in Java using tools like
sablecc, antlr, JLex, CUP and so
forth. This project has has been used
to successfully preprocess much of the
source code of the GNU C library. As
of version 1.2.5, it can also
preprocess the Apple Objective C
library.

http://www.anarres.org/projects/jcpp/

绾颜 2024-08-20 00:49:32

如果您确实需要条件编译并且使用 Ant,您也许可以过滤代码并在其中执行搜索和替换。

例如: http://weblogs.java.net/blog /schaefa/archive/2005/01/how_to_do_condi.html

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

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

If you really need conditional compilation and you use Ant, you might be able to filter your code and do a search-and-replace in it.

For example: http://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html

In the same manner you can, for example, write a filter to replace LOG.debug(...); with /*LOG.debug(...);*/. This would still execute faster than if (LOG.isDebugEnabled()) { ... } stuff, not to mention being more concise at the same time.

If you use Maven, there is a similar feature described here.

暖阳 2024-08-20 00:49:32

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

插件网址:
https://manifold.systems/

预处理器信息:
https://github.com/manifold- Systems/manifold/tree/master/manifold-deps-parent/manifold-preprocessor

PS:我不隶属于他们,我们只是碰巧使用它,它在没有工作流程的情况下有很大帮助(这可能不是)典型的 Java 开发)

If you use IntelliJ there is a plugin called Manifold, that - along with many other features - allows one to use #ifdef and #define in Java.

Plugin url:
https://manifold.systems/

Preprocessor information:
https://github.com/manifold-systems/manifold/tree/master/manifold-deps-parent/manifold-preprocessor

PS: I am not affiliated with them, we just happen to use it, and it helps a lot with out workflow (which is likely NOT typical for Java development)

雄赳赳气昂昂 2024-08-20 00:49:32

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

现在对象创建时间不再是问题了,不是吗?当在较长的运行时间段内进行平均时,所花费的时间的最大部分现在应该是在主算法上,不是吗?

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

Use the Factory Pattern to switch between implementations of a class?

The object creation time can't be a concern now could it? When averaged over a long running time period, the biggest component of time spent should be in the main algorithm now wouldn't it?

Strictly speaking, you don't really need a preprocessor to do what you seek to achieve. There are most probably other ways of meeting your requirement than the one I have proposed of course.

假扮的天使 2024-08-20 00:49:32
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文