2011-12-31 10 views
59

При добавлении 'a' + 'b' он производит 195. Является ли выходным типом данных char или int?В Java, является результатом добавления двух символов int или char?

+2

Если тип был 'char' того значения' 'а' + 'b'' не будет '195', но'' Ã'' – Joren

+1

это 195 здесь - http://ideone.com, но не в Eclipse. – orange

+2

Вы читаете, что из книги Алгоритмов LOL! Я пришел сюда из-за этого упражнения точно;) –

ответ

108

В результате добавления Java-символов, шорты, или байт является INT:

Java Language Specification on Binary Numeric Promotion:

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

But note what it says about compound assignment operators (like +=):

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

Например:

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 bytecode даже не имеет специальных инструкций для арифметики с меньшими типами данных. Например, для добавления есть инструкции iadd (для целых чисел), ladd (для длин), fadd (для поплавков), dadd (для парных), и все. Чтобы имитировать x += y с меньшими типами, компилятор будет использовать iadd и затем обнулить верхние байты int с помощью команды типа i2c («int to char»). Если у родного процессора есть выделенные инструкции для 1-байтовых или 2-байтовых данных, для виртуальной машины Java это будет оптимизировано во время выполнения.

Если вы хотите объединить символы как строку, а не интерпретировать их как числовой тип, существует множество способов сделать это. Самый простой - добавить в выражение пустую строку, потому что добавление символа и строки приводит к String.Все эти выражения приводят в строке "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')
+1

Очень интересный и информативный ответ, спасибо! Заметьте, я лично добавлю раздел об использовании формата String (так как это приятная для чтения альтернатива), но я действительно nitpicking: P –

19

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

+1

И унарные арифметические операции. –

2

В соответствии с binary promotion rules, если ни один из операндов не является двойным, поплавковым или длинным, оба могут быть увеличены до int. Тем не менее, я настоятельно рекомендую относиться к типу char как числовому, такого рода поражения его цели.

+0

Использование 'char' в качестве числового значения целиком и полностью целиком, поэтому JLS выделяет столько аргументов для такого использования. –

6

Возможно, вы захотите узнать следующие выражения о 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 и строковый тип переменной temp автоматически принимает c типа полукокса и производит 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 является одним из лучших источников для этого: Conversions and Promotions. В частности, прочитайте короткий бит на «5.1.2 Расширение примитивного преобразования».

3

Компилятор Java может интерпретировать его как один.

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

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

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

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

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

INT: 195

символ: Ã

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

char result2 = 'a' + 'b' 

выполняется неявное преобразование («примитивное сужение con версия "от int до char).

+0

Я удивлен, что вы не получили предупреждение о компиляторе во втором случае о возможной потере точности из-за сужения. –

+0

@eboix: вы написали * «компилятор автоматически добавляет либо char, либо int» * [sic] ... Что неверно, потому что * int * не «отливается» от * int * и переходит из * int * to * char * не называется «литой», а «сужающей примитивной конверсией»;) – TacticalCoder

+0

Да. Я тоже этого ожидал. Я фактически написал часть своего ответа об этом, прежде чем делать свою программу, но затем я удалил ее, увидев, что у меня нет никаких предупреждений или ошибок. – eboix

1

Хотя у вас уже есть правильный ответ (ссылка на 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

0

Вот что-то странное, хотя. Следующие компилирует:

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

Но это не так:

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

Казалось бы, что оба выражения («а» + «б» и х + «б») приводят в целых числах, следующим test:

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

char x = 'a'; 
Object obj2 = x+'b'; 
System.out.println(obj2.getClass().getName()); 

Так почему же второй случай не скомпилирован? Кстати, вы можете это исправить путем литья все выражение как полукокса:

x = (char)(x+'b'); 

Это выглядит как непоследовательность в семантике Java - любое выражение, символ должен быть взаимозаменяемыми с другим в любом контексте. Кто-нибудь знает, как это понять?

1

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

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

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

2.) Применить преобразование Hexadecimal to Decimal а затем выполните операцию по значениям Decimal.

char  Unicode  Decimal 
    a   0061   97 
    b   0062   98 + 
           195 

Unicode To Decimal Converter

Пример

0061 

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

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

0 + 0 + 96 + 1 = 97

0062 

(0 * 16) + (0 * 16) + (6 * 16) + (2 * 16)

(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 %