Конкатенация символов для формирования строки дает разные результаты
Почему, когда я использую операцию ниже для суммирования символов, она возвращает числа вместо символов? Разве он не должен давать тот же результат?
ret += ... ; // returns numbers
ret = ret + ...; // returns chars
Код ниже дублирует символы:
doubleChar ( "The" ) → "TThhee"
public String doubleChar(String str) {
String ret = "";
for(int i = 0; i < str.length(); i++) {
ret = ret + str.charAt(i) + str.charAt(i); // it concatenates the letters correctly
//ret += str.charAt(i) + str.charAt(i); // it concatenates numbers
}
return ret;
}
Ответы
Ответ 1
Результат следующего выражения
ret + str.charAt(i) + str.charAt(i);
является результатом конкатенации строк. Состояние спецификации языка Java
Результат конкатенации строк - это ссылка на объект String это конкатенация двух операндных строк. Персонажи левого операнда предшествуют символам правого операнд во вновь созданной строке.
Результат
str.charAt(i) + str.charAt(i);
- результат аддитивного оператора, применяемого к двум числовым типам. Состояние спецификации языка Java
Оператор binary + выполняет добавление при применении к двум операндам числового типа, производя сумму операндов. [...] Тип аддитивного выражения для числовых операндов - продвинутыйтип его операндов.
В этом случае
str.charAt(i) + str.charAt(i);
становится int
, удерживая сумму двух значений char
. Затем он конкатенируется с ret
.
Вы также можете знать это о выражении составного назначения +=
Совокупное присваивание выражения формы E1 op= E2
эквивалентно до E1 = (T) ((E1) op (E2))
, где T
- тип E1
, за исключением того, что E1
оценивается только один раз.
Другими словами
ret += str.charAt(i) + str.charAt(i);
эквивалентно
ret = (String) ((ret) + (str.charAt(i) + str.charAt(i)));
| ^ integer addition
|
^ string concatenation
Ответ 2
Первый пример
Из семантики, я бы сказал, что мы смотрим на arithmetic promotion
на работе. Обратите внимание на первый пример:
String + char + char
Из-за арифметического продвижения эти два значения char
повышаются до значений String
, поэтому типы становятся:
String + String + String
+
перегружен, чтобы выполнить конкатенацию, потому что все операнды имеют тип String
.
Второй пример
Во втором примере, как и во всех присваиваниях, сначала оцениваем правую часть оператора =
и что у нас есть?
char + char
char интерпретируется как его числовое значение, поскольку для String
не существует String
, и мы имеем числовое дополнение, которое затем добавляется к String
.
Дополнительное чтение
Некоторые заметки об арифметическом продвижении можно найти здесь.
Некоторые примечания по оценке выражений можно найти здесь.
Ответ 3
В первом примере вы явно добавляете строку в качестве первого слова. Это заставляет второй и третий термины также продвигаться к String (s). Во втором случае вы добавляете два символа (которые затем присоединяются к String) - он не продвигает строку до назначения. Вы могли бы быть явным, используя Character.toString() или String. valueOf() так
ret += Character.toString(str.charAt(i)) + String.valueOf(str.charAt(i));
Ответ 4
Из спецификации Java:
15.26.2. Операторы присваивания соединения
Совокупное выражение выражения формы E1 op= E2
эквивалентно E1 = (T) ((E1) op (E2))
, где T
- тип E1
, за исключением того, что E1
оценивается только один раз.
Таким образом, оператор +=
имеет встроенный приведение к типу назначения.
Напротив, предложение для простого назначения говорит:
15.26.1. Простой оператор присваивания =
Ошибка компиляции, если тип правого операнда не может быть преобразован в тип переменной путем преобразования присваивания (§5.2).
Здесь
ret = ret + str.charAt(i) + str.charAt(i);
рассматривается как конкатенация строк.
и
ret += str.charAt(i) + str.charAt(i);
рассматривается как аддитивная операция.
Ответ 5
ret = ret + str.charAt(i) + str.charAt(i);////он правильно конкатенирует буквы
Это потому, что ret является строкой snd, которая объединяется с другими символами.
ret + = str.charAt(i) + str.charAt(i);//он объединяет числа
Это потому, что компилятор сначала оценивает "str.charAt(i) + str.charAt(i)", что, вероятно, приводит к числу, а затем объединяет его с ret. Поэтому по существу мы оцениваем левую сторону и затем назначаем ее.
Надеюсь, он очистит ваше замешательство.