В Java результатом добавления двух символов является int или char?

При добавлении 'a' + 'b' получается 195. Тип выходных данных char или int?


person orange    schedule 31.12.2011    source источник
comment
Если бы тип был char, то значение 'a' + 'b' было бы не 195, а 'Ã'.   -  person Joren    schedule 01.01.2012
comment
Здесь 195 - ideone.com, но не в Eclipse.   -  person orange    schedule 01.01.2012
comment
Вы прочитали это из книги «Алгоритмы», лол! Я пришел сюда именно из-за этого упражнения ;)   -  person Jack Twain    schedule 27.04.2015
comment
Java (OpenJDK 8) - Try It Онлайн   -  person    schedule 03.04.2021


Ответы (8)


Результатом добавления символов Java, шорт или байтов является int:

Спецификация языка Java для преобразования двоичных чисел:

  • Если какой-либо из операндов имеет ссылочный тип, выполняется преобразование распаковки (§5.1.8). Потом:
  • Если один из операндов имеет тип double, другой преобразуется в double.
  • В противном случае, если один из операндов имеет тип float, другой преобразуется в float.
  • В противном случае, если один из операндов имеет тип long, другой преобразуется в long.
  • В противном случае оба операнда преобразуются в тип int.

Но обратите внимание, что там говорится о составных операторах присваивания (таких как + =):

Результат бинарной операции преобразуется в тип левой переменной... и результат преобразования сохраняется в переменной.

Например:

char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK

В общем, один из способов узнать тип результата — привести его к объекту и спросить, к какому классу он относится:

System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer

Если вас интересует производительность, обратите внимание, что байт-код Java даже не содержит специальных инструкций для арифметических операций. с меньшими типами данных. Например, для сложения есть инструкции iadd (для целых чисел), ladd (для длинных чисел), fadd (для чисел с плавающей запятой), dadd (для двойных чисел) и все. Чтобы имитировать x += y с меньшими типами, компилятор будет использовать iadd, а затем обнулять старшие байты int с помощью инструкции типа i2c ("int to char"). Если собственный ЦП имеет специальные инструкции для 1-байтовых или 2-байтовых данных, виртуальная машина Java должна оптимизировать их во время выполнения.

Если вы хотите объединить символы как строку, а не интерпретировать их как числовой тип, есть много способов сделать это. Проще всего добавить в выражение пустую строку, потому что добавление char и строки приводит к строке. Результатом всех этих выражений является строка "ab":

  • 'a' + "" + 'b'
  • "" + 'a' + 'b' (это работает, потому что "" + 'a' оценивается первым; если бы "" было в конце, вместо этого вы получили бы "195")
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')
person Boann    schedule 31.12.2011

Двоичные арифметические операции над char и byteshort) преобразуются в int -- JLS 5.6.2.

person Hot Licks    schedule 31.12.2011
comment
И унарные арифметические операции. - person Tom Hawtin - tackline; 31.12.2011

Вы можете выучить следующие выражения о char.

char c='A';
int i=c+1;

System.out.println("i = "+i);

Это совершенно верно для Java и возвращает 66, соответствующее значение символа (Unicode) c+1.


String temp="";
temp+=c;
System.out.println("temp = "+temp);

Это слишком допустимо в Java, и переменная типа String temp автоматически принимает c типа char и выдает temp=A на консоли.


Все следующие операторы также действительны в Java!

Integer intType=new Integer(c);
System.out.println("intType = "+intType);

Double  doubleType=new Double(c);
System.out.println("doubleType = "+doubleType);

Float floatType=new Float(c);
System.out.println("floatType = "+floatType);

BigDecimal decimalType=new BigDecimal(c);
System.out.println("decimalType = "+decimalType);

Long longType=new Long(c);
System.out.println("longType = "+longType);

Хотя c является типом char, он может быть предоставлен без ошибок в соответствующих конструкторах, и все приведенные выше операторы рассматриваются как допустимые операторы. Они производят следующие выходные данные соответственно.

intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65

char — это примитивный целочисленный числовой тип, и поэтому он подчиняется всем правилам этих зверей, включая преобразования и повышения. Вы захотите прочитать об этом, и JLS является одним из лучших источников для этого: Конверсии и рекламные акции. В частности, прочтите небольшой отрывок из раздела «5.1.2 Расширение примитивного преобразования».

person Lion    schedule 31.12.2011

Компилятор Java может интерпретировать его как любой из них.

Проверьте это, написав программу и поискав ошибки компилятора:

public static void main(String[] args) {
    int result1 = 'a' + 'b';
    char result2 = 'a' + 'b';
}

Если это символ, то первая строка выдаст мне ошибку, а вторая нет. Если это int, то произойдет обратное.

Я скомпилировал его и получил... НЕТ ОШИБОК. Значит, Java поддерживает и то, и другое.

Однако, когда я их напечатал, я получил:

интервал: 195

символ: Ã

Что происходит, когда вы делаете:

char result2 = 'a' + 'b'

выполняется неявное преобразование (примитивное сужающее преобразование из int в char).

person eboix    schedule 31.12.2011
comment
Я удивлен, что вы не получили предупреждение компилятора во втором случае о возможной потере точности из-за сужения. - person Hot Licks; 31.12.2011
comment
@eboix: вы написали, что компилятор автоматически приводит либо к char, либо к int [sic]... Что неверно, поскольку int не приводится к int и переход от int к char называется не приведением, а сужающим примитивным преобразованием; ) - person TacticalCoder; 31.12.2011
comment
Да. Я тоже этого ожидал. На самом деле я написал часть своего ответа об этом перед созданием своей программы, но затем я удалил ее, как только увидел, что у меня нет предупреждений или ошибок. - person eboix; 31.12.2011
comment
@eboix: э-э-э :) Я бы отредактировал это, но у меня еще нет 2 000 очков репутации, поэтому мой комментарий вместо редактирования; ) - person TacticalCoder; 31.12.2011
comment
Если хочешь, @user988052, я могу изменить его обратно на то, что было, и ты сможешь отредактировать его, получая баллы. Вы все еще можете отредактировать его, если у вас меньше 2000 очков репутации. Единственное, что человек, который сделал сообщение, должен принять редактирование. Я верну его прямо сейчас, чтобы вы могли получить два очка, которые по праву принадлежат вам. - person eboix; 31.12.2011
comment
Почему для этой строки выполняется неявное преобразование char result2 = 'a' + 'b'. Но не для чего-то вроде этого char x , y = 2,z=3; х = г + у; - person matt; 05.08.2017
comment
@matt - Потому что z + y не является постоянным выражением. Смотрите мой ответ для более подробного объяснения... со ссылками JLS. - person Stephen C; 24.05.2020

В соответствии с правилами продвижения двоичных файлов, если ни операндов является двойным, плавающим или длинным, оба повышаются до int. Тем не менее, я настоятельно рекомендую не рассматривать тип char как числовой, так как это противоречит его назначению.

person Sergei Tachenov    schedule 31.12.2011
comment
Использование char в качестве числового значения полностью соответствует его назначению, поэтому JLS уделяет такому использованию так много слов. - person Lew Bloch; 07.01.2017

Хотя у вас уже есть правильный ответ (упоминаемый в JLS), вот небольшой код, чтобы убедиться, что вы получаете int при добавлении двух char.

public class CharAdditionTest
{
    public static void main(String args[])
    {
        char a = 'a';
        char b = 'b';

        Object obj = a + b;
        System.out.println(obj.getClass().getName());
    }
}

Выход

java.lang.Integer

person Paul    schedule 31.12.2011
comment
Это не убедительная проверка, потому что вы добавили в смесь конверсию бокса. Типы int и Integer — это не одно и то же. Более убедительная проверка — попытаться присвоить a + b переменной int или переменной char. Последний выдает ошибку компиляции, которая говорит о том, что вы не можете присвоить int char. - person Stephen C; 24.05.2020

char представлен как Unicode и где значения Unicode представлены \u, за которым следует Hexadecimal значений.

Как и любая арифметическая операция над char значениями, преобразованными в int , результат 'a' + 'b' вычисляется как

1.) Примените значения Unicode к соответствующему char, используя Unicode Table.

2.) Примените преобразование шестнадцатеричных чисел в десятичные, а затем выполните операцию на Decimal значения.

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

Пример

0061

(0*163) + (0*162) + (6*161) + (1*160 )

(0*4096) + (0*256) + (6*16) + (1*1)

0 + 0 + 96 + 1 = 97

0062

(0*163) + (0*162) + (6*161) + (2*160 )

(0*4096) + (0*256) + (6*16) + (2*1)

0 + 0 + 96 + 2 = 98

Отсюда 97 + 98 = 195


Пример 2

char        Unicode      Decimal
 Ջ           054b         1355
 À           00c0          192 
                      --------
                          1547    +
                          1163    -
                             7    /
                        260160    *
                            11    %
person Pavneet_Singh    schedule 03.02.2017
comment
Это не то, о чем задается вопрос. - person Stephen C; 24.05.2020
comment
К вашему сведению, мой подробный ответ на комментарий выше был удален модами, которые объяснили причину переноса моего ответа из удаленного сообщения. если мой ответ был удален, чтобы скрыть недостатки модерации SO, то вы можете хотя бы удалить вышеуказанный комментарий или как-то указать аудиторию, чтобы мне не пришлось писать еще один комментарий? вопросы к SO модам - person Pavneet_Singh; 25.05.2020
comment
Я остаюсь при своем комментарии. Поскольку я ответил вам ... но затем удалил ... причина, по которой вы разместили этот Вопрос здесь, не меняет того факта, что он на 95% не соответствует теме вопроса и на 5% повторяет более ранние ответы. Если вы хотите сохранить результаты потраченных впустую усилий, было бы правильнее сохранить их на жестком диске. Или найдите другой вопрос, к которому он относится. - person Stephen C; 25.05.2020
comment
Если у вас есть претензии к модераторам, решите их на сайте meta.stackoverflow.com. И предоставить доказательства. Все, что я пытаюсь здесь сделать, это привести в порядок ››эти‹‹ вопросы и ответы. - person Stephen C; 25.05.2020
comment
Я понимаю вашу точку зрения, но не могу понять факт игнорирования деталей преобразования Unicode с примерами в качестве дополнительного значения, которое может помочь некоторым читателям, поэтому я хотел бы сохранить этот ответ (я понимаю, что это бесполезно для вас и кажется неправильным) тема). Я избегаю мета и подобных мест, так как без силы и поддержки делать такие вещи непросто, на это уходит много времени, сил. Я предпочитаю сохранять внутренний покой, сир. - person Pavneet_Singh; 25.05.2020
comment
Что ж, оставление рецепта приготовления фруктовых тортов также может помочь читателю ... если он пытается испечь фруктовый пирог. Если пользователь пытается понять детали преобразования Unicode, он, скорее всего, использовал другие условия поиска и в конечном итоге получил совершенно другой вопрос. Чтобы этот ответ был полезным, он должен быть на ››этом‹‹ вопросе. ››Это‹‹ вопрос касается типа результата, а не значения. - person Stephen C; 25.05.2020
comment
Это будет та же ситуация (как объяснено в первоначальном комментарии), хотя спасибо за предложение. - person Pavneet_Singh; 25.05.2020

Хотя ответ Боанна правильный, существует сложность, которая применяется к случаю константных выражений, когда они появляются в контекстах назначения.

Рассмотрим следующие примеры:

  char x = 'a' + 'b';   // OK

  char y = 'a';
  char z = y + 'b';     // Compilation error

Что здесь происходит? Они имеют в виду одно и то же, не так ли? И почему законно присваивать int char в первом примере?

Когда постоянное выражение появляется в контексте присваивания, компилятор Java вычисляет значение выражения и проверяет, находится ли оно в диапазоне типа, которому вы присваиваете значение. Если это так, то применяется неявное сужающее примитивное преобразование.

  • В первом примере 'a' + 'b' является константным выражением, и его значение уместится в char, поэтому компилятор допускает неявное сужение результата выражения int до char.

  • Во втором примере y является переменной, поэтому y + 'b' НЕ является постоянным выражением. Таким образом, несмотря на то, что Blind Freddy может видеть, что значение подходит, компилятор НЕ допускает каких-либо неявных сужается, и вы получаете ошибку компиляции, говорящую о том, что int не может быть присвоено char.

Есть и другие предостережения относительно того, когда в этом контексте разрешено неявное сужающее примитивное преобразование; см. JLS 5.2 и JLS 15.28 для Полная информация.

Последний подробно объясняет требования к константному выражению. Это может быть не то, что вы думаете. (Например, простое объявление y как final не поможет.)

person Stephen C    schedule 24.05.2020