11

我想知道Java将如何处理以下场景:

假设我有一个名为 Debug 的类,它看起来像这样:

public class Debug 
{
    private static final boolean isAssertEnabled = true;

    public static void assertTrue(boolean b, String errorMessage) {
        if (isAssertEnabled) {
            if (!b) {
                throw new RuntimeException(errorMessage);
            }
        }
    }
}

并假设我的代码有一个看起来像这样的调用:

...
Debug.assertTrue((x + y != z) && (v - u > w), "Some error message");
....

我有几个问题:

  1. 如果isAssertEnabled标志设置为false,是否会编译出对 Debug.assertTrue 的整个调用?请注意,检查 isAssertEnabled == true 仅在函数调用后在函数内部进行。
  2. 如果整个调用都被编译出来,这是否也意味着布尔表达式的评估被编译出来?毫无意义地评估该表达式将是一种浪费。

谢谢你的帮助!

4

3 回答 3

6

布尔表达式的求值不应该被编译掉——至少通过 javac。

即使Debug类文件当前没有对值做任何事情,谁能说在执行时会出现这种情况?

在使 Debug 类编译(通过使isAssertEnabled静态)之后,javac 仍然包含代码 - 但我希望 JIT 编译器将其删除(尽管您应该看到问题 Peter referenced)。然后它是否可以将该方法内联为空,我不确定。同样,如果 JIT 编译器可以做到这一点,并且如果它意识到评估参数不会有任何副作用,它可能会避免评估。不过,我不会亲自编写代码。

于 2011-01-21T07:47:49.087 回答
3

你为什么要构建 Java 已经提供的原生功能?

assert关键字完全符合您的要求:可以打开和关闭它的执行(在每个包级别上),并且在禁用断言时避免布尔表达式的评估。

于 2011-01-21T08:21:59.933 回答
2

这让我想起了 Log4j 的“isTraceEnabled()”、“isDebugEnabled()”等等。必须在 if 语句中显式地包装您的日志语句,以避免不必要的日志语句评估。

if(logger.isDebugEnabled() {
        logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

请参阅“性能”下的此处

于 2011-01-21T07:58:57.487 回答