При добавлении 'a' + 'b'
он производит 195. Является ли выходным типом данных char
или int
?В Java, является результатом добавления двух символов int или char?
ответ
В результате добавления 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')
Очень интересный и информативный ответ, спасибо! Заметьте, я лично добавлю раздел об использовании формата String (так как это приятная для чтения альтернатива), но я действительно nitpicking: P –
Бинарные арифметические операции над char
и byte
(и short
) способствуют int
- JLS 5.6.2.
И унарные арифметические операции. –
В соответствии с binary promotion rules, если ни один из операндов не является двойным, поплавковым или длинным, оба могут быть увеличены до int. Тем не менее, я настоятельно рекомендую относиться к типу char как числовому, такого рода поражения его цели.
Использование 'char' в качестве числового значения целиком и полностью целиком, поэтому JLS выделяет столько аргументов для такого использования. –
Возможно, вы захотите узнать следующие выражения о 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 Расширение примитивного преобразования».
Компилятор 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).
Я удивлен, что вы не получили предупреждение о компиляторе во втором случае о возможной потере точности из-за сужения. –
@eboix: вы написали * «компилятор автоматически добавляет либо char, либо int» * [sic] ... Что неверно, потому что * int * не «отливается» от * int * и переходит из * int * to * char * не называется «литой», а «сужающей примитивной конверсией»;) – TacticalCoder
Да. Я тоже этого ожидал. Я фактически написал часть своего ответа об этом, прежде чем делать свою программу, но затем я удалил ее, увидев, что у меня нет никаких предупреждений или ошибок. – eboix
Хотя у вас уже есть правильный ответ (ссылка на 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
Вот что-то странное, хотя. Следующие компилирует:
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 - любое выражение, символ должен быть взаимозаменяемыми с другим в любом контексте. Кто-нибудь знает, как это понять?
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
Пример
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 %
Если тип был 'char' того значения' 'а' + 'b'' не будет '195', но'' Ã'' – Joren
это 195 здесь - http://ideone.com, но не в Eclipse. – orange
Вы читаете, что из книги Алгоритмов LOL! Я пришел сюда из-за этого упражнения точно;) –