将在常量池中创建多少个字符串对象

时间:2013-10-29 09:32:43

标签: java string logging log4j

考虑以下语句并将日志级别设置为ERROR。正在使用的日志API是log4j。 鉴于以上信息,将创建多少个字符串?

if (logger.isDebugEnabled()) {
    logger.debug("Executing SQL query [" + sql + "]");
}

其他问题是

if (logger.isDebugEnabled()) {
     StringBuilder sBuilder = new StringBuilder("Executing SQL query [");
     sBuilder.append(sql);
     sBuilder.append("]");
     logger.debug(sBuilder.toString());
}

在上述情况下会创建多少个字符串?

我的问题是,即使没有为调试启用记录器,编译器也会创建字符串吗?

2 个答案:

答案 0 :(得分:2)

logger.debug("Executing SQL query [" + sql + "]");

两个字符串

"Executing SQL query [" 

"]"

在编译时创建。

然后,在运行时,

"Executing SQL query [" + sql + "]"

(+)operator JVM返回新的StringBuilder(string ...)。toString(),它在堆内存中创建 new String 实例。

如果调试启用,则StringBuilder.toString将发生追加操作。

答案 1 :(得分:2)

如果源代码中有引号,那么无论代码有多复杂,编译器都会将字符串保持为常量。编译器没有做出很多假设,除非它能清楚地看到代码无法访问(如if(false))。

您可能希望看一下带有logback的slf4j,它允许您编写

log.debug("Executing SQL query [{}]", sql);

请注意,在运行时,它仍会创建StringBuilder并根据模式和参数构建结果,但slf4j将为您执行if。这将使您的代码保持清洁和快速,而无需花费太多精力。

您可能希望查看project Lombok及其@Log annotation,以使其更轻松,更紧凑。