问题
When we split a long line of code into two for readability, it introduces a plus sign between the lines (if split between the text). For example splitting a long line in middle of text which is logging some text.
So, this should be avoided given additional string concatenation it brings into picture ? Or trade off of better readability weighs higher ?
回答1:
All the usual Java compilers are way too mature to do something dumb like concatenate string literals at run time. Let's check. Given this code:
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);
}
}
My Java 8 compiler - Oracle standard - does the right thing as shown by javap output:
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
回答2:
Yes, there is a tiny bit of performance impact. The regular compiler doesn't do any optimization. It simply replaces the + operator with StringBuilder method calls. E.g. if you have String s = "x" + "y" + "z";, it may be replaced by String s = new StringBuilder().append("x").append("y").append("z"); before being compiled into bytecodes. But there is no real optimization here. It doesn't replace it by String s = "xyz"; before producing the byte code. I am not sure if the JIT compiler optimizes it before generating the native processor instructions. But even if it does, it is at run time causing a tiny performance hit.
Personally, I would care more for elegance and readability if they come at a cost of tiny performance hit.
回答3:
It depends.
If the there are only constants, the javac takes care of it. The following program:
public class Main {
public static void main(String[] args) {
System.out.println("foo"+"bar");
}
}
Turns into the following bytecode (removed some non relevant parts):
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
}
You can see the foobar constant in there. So in this case there is no performance hit.
However if we would change the program to something more realistic:
public class Main {
public static void main(String[] args) {
int a = 1;
System.out.println(a+"foo" + "bar");
}
}
We get the following bytecode:
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.<init> ()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
}
As you can see, "foo" and "bar" are not automatically concatenated.
I have no idea if the JIT is able to remove the unwanted concatenation.
来源:https://stackoverflow.com/questions/41540849/performance-issue-with-splitting-long-log-line-into-two