It's not a complete answer, but it gives you an idea.
I've compiled the following class with javac 1.8.0_111:
public class Teste {
public String x() {
String s1 = "s1";
String s2 = new String("s2");
String s3 = "s3";
String s4 = s3 + "s4";
String s5 = "s5";
String s6 = s5 + "-" + "s6";
final String s7 = "s7";
String s8 = s7 + "s8";
final String s9 = "s9";
String s10 = s9 + "-" + "s10";
return s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
}
}
And I decompiled the result:
/*
* Decompiled with CFR 0_118.
*/
public class Teste {
public String x() {
String string = "s1";
String string2 = new String("s2");
String string3 = "s3";
String string4 = string3 + "s4";
String string5 = "s5";
String string6 = string5 + "-s6";
String string7 = "s7s8";
String string8 = "s9-s10";
return string + string2 + string3 + string4 + string5 + string6 + "s7" + string7 + "s9" + string8;
}
}
Using another decompiler:
//
// Decompiled by Procyon v0.5.30
//
public class Teste
{
public String x() {
final String s = "s1";
final String s2 = new String("s2");
final String s3 = "s3";
final String string = s3 + "s4";
final String s4 = "s5";
return s + s2 + s3 + string + s4 + (s4 + "-s6") + "s7" + "s7s8" + "s9" + "s9-s10";
}
}
Note that the compiler was clever and has already done some of the concatenations by itself, and therefore the result will not always be obvious. However, clearly, he could be even smarter than he is.
I tried to make a variant by removing the final
modifiers, believing it would not make any difference. To my surprise, final
made a difference yes. Here are the results of decompiling:
/*
* Decompiled with CFR 0_118.
*/
public class Teste2 {
public String x() {
String string = "s1";
String string2 = new String("s2");
String string3 = "s3";
String string4 = string3 + "s4";
String string5 = "s5";
String string6 = string5 + "-s6";
String string7 = "s7";
String string8 = string7 + "s8";
String string9 = "s9";
String string10 = string9 + "-s10";
return string + string2 + string3 + string4 + string5 + string6 + string7 + string8 + string9 + string10;
}
}
//
// Decompiled by Procyon v0.5.30
//
public class Teste2
{
public String x() {
final String s = "s1";
final String s2 = new String("s2");
final String s3 = "s3";
final String string = s3 + "s4";
final String s4 = "s5";
final String string2 = s4 + "-s6";
final String s5 = "s7";
final String string3 = s5 + "s8";
final String s6 = "s9";
return s + s2 + s3 + string + s4 + string2 + s5 + string3 + s6 + (s6 + "-s10");
}
}
I also tried another variant, putting final
on all variables:
/*
* Decompiled with CFR 0_118.
*/
public class Teste3 {
public String x() {
String string = new String("s2");
return "s1" + string + "s3" + "s3s4" + "s5" + "s5-s6" + "s7" + "s7s8" + "s9" + "s9-s10";
}
}
//
// Decompiled by Procyon v0.5.30
//
public class Teste3
{
public String x() {
return "s1" + new String("s2") + "s3" + "s3s4" + "s5" + "s5-s6" + "s7" + "s7s8" + "s9" + "s9-s10";
}
}
That is, the code with final
compiles better.