Конкатенация символов для формирования строки дает разные результаты

Почему, когда я использую операцию ниже для суммирования символов, она возвращает числа вместо символов? Разве он не должен давать тот же результат?

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. Поэтому по существу мы оцениваем левую сторону и затем назначаем ее.

Надеюсь, он очистит ваше замешательство.