При додаванні 'a' + 'b'виходить 195. Вихідний тип даних charчи int?
При додаванні 'a' + 'b'виходить 195. Вихідний тип даних charчи int?
Відповіді:
Результатом додавання символів Java, шортів або байтів 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(для ints), ladd(для longs), fadd(для floats), dadd(для парних), і все. Для імітації x += yз меншими типами компілятор використовує, iaddа потім обнуляє верхні байти int, використовуючи інструкцію типу i2c("int to char"). Якщо власний центральний процесор має спеціальні інструкції щодо 1-байтових або 2-байтових даних, віртуальна машина Java повинна оптимізувати для цього під час роботи.
Якщо ви хочете об’єднати символи як рядок, а не інтерпретувати їх як числовий тип, існує безліч способів зробити це. Найпростішим є додавання порожнього рядка до виразу, оскільки додавання символу та рядка призводить до отримання рядка. Усі ці вирази призводять до рядка "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')Двійкові арифметичні операції над charта byte(і short) сприяння int- JLS 5.6.2.
Можливо, ви захочете вивчити наступні вислови щодо 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 Розширення примітивного перетворення".
Компілятор Java може інтерпретувати його як один із них.
Перевірте це, написавши програму та шукаючи помилки компілятора:
public static void main(String[] args) {
int result1 = 'a' + 'b';
char result2 = 'a' + 'b';
}
Якщо це символ, то перший рядок дасть мені помилку, а другий - ні. Якщо це int, то станеться навпаки.
Я скомпілював його і отримав ..... ПОМИЛОК НІ. Отже, Java приймає обидва.
Однак, коли я їх надрукував, я отримав:
int: 195
char: Ã
Що трапляється, коли ви робите:
char result2 = 'a' + 'b'
виконується неявне перетворення ("примітивне звуження перетворення" з int на char ).
Відповідно до бінарних правил просування , якщо жоден з операндів не є подвійним, плаваючим або довгим, обидва підвищуються до int. Однак я наполегливо раджу не розглядати тип char як числовий, що перешкоджає його цілі.
charяк числового значення цілком відповідає його цілі, саме тому JLS приділяє стільки багатослів'я такому використанню.
Поки ви вже маєте правильну відповідь (на яку посилається JLS), ось трохи коду, щоб перевірити, чи отримаєте ви intпри додаванні двох chars.
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
intі Integerце не одне і те ж. Більш переконливим підтвердженням полягає в спробі привласнити a + bдо intзмінної або charзмінною. Остання видає помилку компіляції, яка фактично говорить "ви не можете призначити inta для char".
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
Приклад
0061
(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (1 * 16 0 )
(0 * 4096) + (0 * 256) + (6 * 16) + (1 * 1)
0 + 0 + 96 + 1 = 97
0062
(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (2 * 16 0 )
(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 x = 'a' + 'b'; // OK
char y = 'a';
char z = y + 'b'; // Compilation error
Що відбувається? Вони означають одне і те ж, чи не так? І чому в першому прикладі правомірно присвоювати intа char?
Коли константний вираз з'являється в контексті присвоєння, компілятор Java обчислює значення виразу і перевіряє, чи перебуває воно в діапазоні типу, якому ви призначаєте. Якщо це так, то застосовується неявне звужувальне примітивне перетворення .
У першому прикладі 'a' + 'b'це константний вираз, і його значення впишеться в a char, тому компілятор дозволяє неявне звуження intрезультату виразу до a char.
У другому прикладі yє змінною, тому y + 'b'НЕ є постійним виразом. Отже, незважаючи на те, що Сліпий Фредді бачить, що значення буде відповідати, компілятор НЕ допускає неявного звуження, і ви отримуєте помилку компіляції, яка говорить, що intнеможливо присвоїти char.
Є деякі інші застереження щодо того, коли в цьому контексті допускається неявне звуження примітивного перетворення ; дивіться JLS 5.2 та JLS 15.28 для отримання детальної інформації.
Останній детально пояснює вимоги до постійного виразу . Це може бути не те, що ви можете подумати. (Наприклад, просто оголошення yяк finalне допомагає.)
charтоді значення'a' + 'b'не було б,195але'Ã'