char int дает неожиданный результат

#java #type-conversion #string-concatenation

#java #преобразование типов #конкатенация строк

Вопрос:

Мне нужно напечатать ‘H3110 w0r1d 2.0 true‘ в качестве выходных данных. Ниже приведен написанный код, который выводится как ‘3182 w0r1d 2.0 true’.

 public class HelloWorld {
    public static void main (String[] args){

        char c1= 'H';
        int num1 = 3110;
        char c2='w';
        byte b=0;
        char c3='r';
        int y=1;
        char c4='d';

        float f = 2.0f;
        boolean bool= true;
        String s = c1 num1   " "   c2 b c3 y c4   " "   f   " "   bool;
        System.out.println(s);
    }
}
 

Запрос: Если я объединяю H и 3110 , он печатается как 3182 . Почему так?

Комментарии:

1. Потому char int что, по сути, продвигается до добавления. Если вместо этого вы используете строку ( string c1 = "H"; ), все будет хорошо.

2. В подобной ситуации char int char сначала преобразуется int в (соответствующее значение в Юникоде (для начинающих, в данном случае индекс в таблице ASCII)), а затем это обычное int int дополнение.

Ответ №1:

Оператор не использует конкатенацию строк, если хотя бы один операнд не имеет тип String . Игнорируя остальные операторы, вы в основном ищете «что произойдет, если я добавлю char и int вместе» — и ответ: « char повышается до int , и выполняется обычное сложение целых чисел». Повышенное значение 'H' равно 72 (поскольку это числовое значение ‘H’ в формате UTF-16), следовательно, результат 3182.

Самым простым решением для этого в вашем случае было бы изменить тип c1 на String вместо char :

 String c1 = "H";
 

Тогда вместо сложения целых чисел будет использоваться конкатенация строк.

Комментарии:

1. Ну, если быть точным, 'H' равно 72 даже без повышения до int , поскольку char это 16-разрядное целое число без знака в соответствии со спецификацией языка Java.

2. Хорошее объяснение, однако использование StringBuilder безопаснее.

3. @IQbrod Safer может быть неправильным термином, объясняющим, почему StringBuilder следует предпочесть. Производительность может быть более точной. Однако обратите внимание, что в этой конкретной ситуации это не применимо, поскольку Java уже оптимизирует конкатенацию с одним оператором, т.Е. a b c d (Используя сам StringBuilder в более ранних версиях и даже улучшенные механизмы впоследствии).

Ответ №2:

Вы должны использовать StringBuilder введенный в Java 5, который имеет методы .append() с char / int / long и т.д… Этот класс является правильным конкатенатором строк в Java и позволяет вам объединять любой примитив (char / int / long …) по его строковому представлению.

 System.out.println(4 3 "s"); // will print "7s"
System.out.println(StringBuilder.append(4).append(3).append("s").toString()); // will print "43s"
 

Как упоминалось @Zabuzard, компилятор Java заменит строку sum ( ) на a StringBuilder , но char int возвращает an int int не является a String ).
Чтобы получить подробное объяснение о char int возврате int . Я предлагаю вам @JonSkeet ответить 🙂

 public class Main {
    public static void main(String[] args) {
        char c1= 'H';
        int num1 = 3110;
        char c2='w';
        byte b=0;
        char c3='r';
        int y=1;
        char c4='d';

        float f = 2.0f;
        boolean bool= true;
        String s = new StringBuilder()
                .append(c1)
                .append(num1)
                .append(c2)
                .append(b)
                .append(c3)
                .append(y)
                .append(c4)
                .append(f)
                .append(bool)
                .toString();
        System.out.println(s);
    }
}
 

Комментарии:

1. Хотя этот ответ дает ценное решение, было бы также неплохо, если бы он объяснил проблему OPs и почему она устраняет проблему.

2. @Zabuzard Джон сделал это отлично, я не буду копировать и вставлять его ответ

3. Справедливо. Однако обратите внимание , что в этой конкретной ситуации StringBuilder простая конкатенация не имеет никаких преимуществ a b c d . Поскольку JLS требует, чтобы любая реализация Java уже оптимизировала такие конкатенации. StringBuilder имеет преимущества в производительности только в том случае, если конкатенация выполняется по нескольким операторам (обычно в цикле).

4. OP ожидает в качестве конкатенатора строк, но в Java используется правильный конкатенатор строк, StringBuilder.append() который предотвращает путаницу char int при возврате int

5. Это справедливо, вот почему я бы предложил добавить более подробное объяснение, чтобы подчеркнуть этот аспект.

Ответ №3:

Другим решением этой проблемы может быть использование статического метода

 String.valueOf(c1)
 

Лучшим способом является использование ранее упомянутого StringBuilder, но использование String.valueOf — другое решение с меньшим эффектом для кода, чем при использовании StringBuilder.

Комментарии:

1. Спасибо всем вам за подробное объяснение