当我们将一长串代码分成两行以便于阅读时,它会在行之间引入一个加号(如果在文本之间分割)。 例如,在正在记录某些文本的文本中间拆分一条长行。
那么,如果它带来了额外的字符串连接,应该避免这种情况吗?或者更好的可读性权衡更高?
答案 0 :(得分:2)
所有常见的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
答案 1 :(得分:1)
是的,会有一点点性能影响。常规编译器不进行任何优化。它只是用StringBuilder
方法调用替换+运算符。例如。如果您有String s = "x" + "y" + "z";
,则在编译为字节码之前,它可能会被String s = new StringBuilder().append("x").append("y").append("z");
替换。但这里没有真正的优化。在生成字节代码之前,它不会用String s = "xyz";
替换它。我不确定JIT编译器在生成本机处理器指令之前是否优化它。但即使它确实如此,它在运行时会导致性能受到轻微打击。
就个人而言,如果它们以微小的性能损失为代价,我会更加关注优雅和可读性。
答案 2 :(得分:1)
取决于。
如果只有常量,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.<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
}
正如你所看到的,&#34; foo&#34;和&#34; bar&#34;不会自动连接。
我不知道JIT是否能够删除不需要的连接。