我刚刚开始使用Java,在阅读this guide时,我注意到以下片段,描述了Junit框架的最新更新。
我们现在可以在JUnit 5中的lambda中编写断言消息,允许延迟评估跳过复杂的消息构造,直到需要:
@Test public void shouldFailBecauseTheNumbersAreNotEqual_lazyEvaluation() { Assertions.assertTrue( 2 == 3, () -> "Numbers " + 2 + " and " + 3 + " are not equal!"); }
作为Java的新手,这感觉就像是一个大型实现,只是为了解决字符串连接问题。
在Java中评估字符串真的很慢(相对于其他语言吗?)。它与C,Golang等其他编译语言相比如何?
关键是:Java中没有惰性字符串格式。
意思是,在像C这样的语言中你可能会看到如下内容:
#define debug_print...
(参见一些现实世界的例子here)
我们的想法是定义一个传递复杂字符串的宏。但是编译器确保仅为实际存在该字符串的情况生成代码。
含义:当使用debug_print()
时,可能需要构建传递给宏调用的消息的复杂字符串concat仅在真正需要消息时才会发生!该消息被懒惰地连接起来。
在Java中,我们根本无法表达这一点。你总是要去
if (someCondition) {
then pull together that large string
这不好,特别是在进行追踪时。我们小组中的一些人编写了这些代码,并且每个和任何跟踪语句都具有该前导if语句,这简直太烦人了。这使得整个代码的可读性降低。
因此:这根本不是字符串连接的成本。如果确实需要该字符串,那么它只需花费所需的CPU周期。
并回答实际问题:最后,当代码经常被调用时,JIT无论如何都会将其转换为精心优化的机器代码。因此:实际的字符串连接不是问题。
换句话说:在源代码方面,您没有想到Java的“性能”。重要的是JIT在运行时发生的事情。
这是底线。从Java开始,不要担心像String连接这样的小问题。对于大型应用程序服务器而言,这可能是一个小问题,其中完成了大量字符串连接但未使用结果。一个示例是日志记录,其中日志级别导致事件被忽略。此外,Java使用StringBuilder来连接由“+”运算符分隔的一系列文字,这些文字具有合理的性能。