Ответ Клинта в порядке, но я остановлюсь на нем дальше и объясню на уровне компилятора.
Как вы знаете, s1
и s2
в конечном итоге станут ссылками на один и тот же экземпляр строки, "Hello"
.
Для s5
и s6
компилятор видит константные выражения. То есть он видит операцию между двумя константами (строковыми литералами). Компилятор знает, как добавить строки и каков будет результат. Поскольку значения известны сразу во время компиляции, он выполняет сложение за вас, в результате чего получается буквенная строка "Hello"
. Следовательно, оно имеет то же значение, что и s1
и s2
, поэтому каждый из них будет ссылаться на один и тот же экземпляр.
s7
нельзя упростить таким же образом. s7
изначально начинается с "He"
конечно. Разница здесь в том, что s7 = s7.concat("llo");
переназначает s7
на результат вызова функции. Это не может быть упрощено как есть. Что касается компилятора Java, результаты всех вызовов функций не известны во время компиляции. Поскольку он не знает результирующего значения, его нельзя упростить, и он остается как есть. Результирующий вызов возвращает новый экземпляр строки "Hello"
, который не совпадает с экземпляром во время компиляции (который разделяет s8
).
s10
нельзя так же упростить. s10
изначально начинается с "He"
, конечно. Затем переназначается s10 = s10 + "llo";
Это не может быть упрощено. Почему вы можете спросить? Ну s10
- это не окончательное выражение переменной. С технической точки зрения, компилятор не знает его значения, потому что он не является константой. Если s10
было объявлено как final String
, то это может быть константа сгиба (при назначении другой переменной).
Итак, рассмотрим эту версию вашего тестового кода:
public static void main(String[] args)
{
String s1 = "Hello";
String s2 = "Hello";
System.out.println("1: s1 == s2 " + (s1 == s2)); // 1
String s3 = "Hel" + "lo";
String s4 = "Hel".concat("lo");
System.out.println("2: s1 == s3 " + (s1 == s3)); // 2
System.out.println("3: s1 == s4 " + (s1 == s4)); // 3
String he = "He";
String s5 = he + "llo";
String s6 = he.concat("llo");
System.out.println("4: s1 == s5 " + (s1 == s5)); // 4
System.out.println("5: s1 == s6 " + (s1 == s6)); // 5
final String fhe = "He";
String s7 = fhe + "llo";
String s8 = fhe.concat("llo");
System.out.println("6: s1 == s7 " + (s1 == s7)); // 6
System.out.println("7: s1 == s8 " + (s1 == s8)); // 7
}
Можете ли вы выяснить, какие строки являются правдой?
правда, правда, ложь, ложь, ложь, правда, ложь
Вам может быть интересно, почему 3 и 7 не соответствуют действительности. Короткий ответ, Java-компилятор не был запрограммирован
, чтобы быть достаточно умным, чтобы распознавать вызов concat (), поэтому он рассматривается как обычный вызов функции.