将长日志分为两个的性能问题

当我们将一长串代码分成两行以便于阅读时,它会在行之间引入一个加号(如果在文本之间分割)。 例如,在正在记录某些文本的文本中间拆分一条长行。

因此,如果它带来了额外的字符串连接,应该避免这种情况吗? 或者更好的可读性权衡更高?

所有常见的Java编译器都太成熟了,无法像运行时连接字符串文字那样愚蠢。 让我们检查。 鉴于此代码:

public class CatStrings { public static void main(String [] args) { String a = "This is a long long long string broken up " + "into parts to see if the compiler " + "optimizes the concatenation."; System.out.println(a); } } 

我的Java 8编译器 – Oracle标准 – 做正确的事情,如javap输出所示:

  stack=2, locals=2, args_size=1 0: ldc #2 // String This is a long long long string broken up into parts to see if the compiler optimizes the concatenation. 2: astore_1 3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 6: aload_1 7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 10: return 

是的,会有一点点性能影响。 常规编译器不进行任何优化。 它只是用StringBuilder方法调用替换+运算符。 例如,如果你有String s = "x" + "y" + "z"; ,它可以用String s = new StringBuilder().append("x").append("y").append("z");替换String s = new StringBuilder().append("x").append("y").append("z"); 在被编译成字节码之前。 但这里没有真正的优化。 它不会被String s = "xyz";取代String s = "xyz"; 在生成字节代码之前。 我不确定JIT编译器在生成本机处理器指令之前是否对其进行了优化。 但即使它确实如此,它在运行时会导致性能受到轻微打击。

就个人而言,如果它们以微小的性能损失为代价,我会更加关注优雅和可读性。

这取决于。

如果只有常量,javac会处理它。 以下程序:

 public class Main { public static void main(String[] args) { System.out.println("foo"+"bar"); } } 

变成以下字节码(删除了一些不相关的部分):

 public class com/hazelcast/Main { // access flags 0x9 public static main([Ljava/lang/String;)V L0 LINENUMBER 9 L0 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; LDC "foobar" INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L1 LINENUMBER 10 L1 RETURN L2 LOCALVARIABLE args [Ljava/lang/String; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1 } 

你可以在那里看到foobar常数。 所以在这种情况下没有性能损失。

但是,如果我们将程序更改为更现实的程序:

 public class Main { public static void main(String[] args) { int a = 1; System.out.println(a+"foo" + "bar"); } } 

我们得到以下字节码:

 public class com/hazelcast/Main { // access flags 0x9 public static main([Ljava/lang/String;)V L0 LINENUMBER 9 L0 ICONST_1 ISTORE 1 L1 LINENUMBER 10 L1 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; NEW java/lang/StringBuilder DUP INVOKESPECIAL java/lang/StringBuilder. ()V ILOAD 1 INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder; LDC "foo" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; LDC "bar" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L2 LINENUMBER 11 L2 RETURN L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 LOCALVARIABLE a I L1 L3 1 MAXSTACK = 3 MAXLOCALS = 2 } 

如您所见,“foo”和“bar”不会自动连接。

我不知道JIT是否能够删除不需要的连接。