Примитивный тип "короткий" - литье в Java
У меня вопрос о примитивном типе short
в Java. Я использую JDK 1.6.
Если у меня есть следующее:
short a = 2;
short b = 3;
short c = a + b;
компилятор не хочет компилировать - он говорит, что он "не может преобразовать из int в short" и предлагает сделать команду cast short
, так что это:
short c = (short) (a + b);
действительно работает. Но мой вопрос: зачем мне бросать? Значения a и b находятся в диапазоне short
- диапазон коротких значений равен {-32,768, 32767}.
Мне также нужно включить, когда я хочу выполнить операции -, *,/(я еще не проверял других).
Если я делаю то же самое для примитивного типа int
, мне не нужно бросать aa + bb в int
. Следующее прекрасно работает:
int aa = 2;
int bb = 3;
int cc = aa +bb;
Я обнаружил это при разработке класса, где мне нужно было добавить две переменные типа short, и компилятор хотел, чтобы я сделал бросок. Если я делаю это с двумя переменными типа int
, мне не нужно бросать.
Спасибо вам заблаговременно.
Небольшое замечание: то же самое происходит и с примитивным типом byte
. Итак, это работает:
byte a = 2;
byte b = 3;
byte c = (byte) (a + b);
но это не так:
byte a = 2;
byte b = 3;
byte c = a + b;
Для long
, float
, double
и int
нет необходимости бросать. Только для значений short
и byte
.
Ответы
Ответ 1
Как объясняется в short С# (но также и для других компиляторов языка, например Java)
Существует предопределенное неявное преобразование из short в int, long, float, double или decimal.
Вы не можете неявно преобразовывать нелитературные числовые типы более крупного размера хранилища в короткие (см. таблицу интегральных типов для размеров хранилища интегральных типов). Рассмотрим, например, следующие две короткие переменные x и y:
short x = 5, y = 12;
Следующая операция присваивания приведет к ошибке компиляции , поскольку арифметическое выражение в правой части оператора присваивания по умолчанию принимает значение int.
short z = x + y; // Error: no conversion from int to short
Чтобы устранить эту проблему, используйте команду cast:
short z = (short)(x + y); // OK: explicit conversion
Можно использовать следующие операторы, где целевая переменная имеет тот же размер хранилища или большой размер хранилища:
int m = x + y;
long n = x + y;
Хороший следующий вопрос:
"почему арифметическое выражение в правой части оператора присваивания по умолчанию принимает значение int??
Первый ответ можно найти в:
Классификация и формальная проверка целых константных фальцов
Спецификация языка Java определяет точно, как представляются целые числа и как оценивать целочисленные арифметические выражения. Это важное свойство Java, поскольку этот язык программирования разработан для использования в распределенных приложениях в Интернете. Для выполнения одного и того же результата требуется программа Java, независимо от целевой машины, выполняющей ее.
Напротив, C (и большинство широко используемых императивов и объектно-ориентированные языки программирования) более неряшлив и оставляет многие важные характеристики открытыми. Замысел этого неточного языка спецификация понятна. Те же программы на C должны работать на 16-битных, 32-разрядной или даже 64-разрядной архитектуры путем создания целочисленной арифметики исходные программы с арифметическими операциями, встроенными в целевой процессор. Это приводит к гораздо более эффективному коду, поскольку он может использовать доступные машинные операции. Пока целые вычисления имеют дело только с причем числа "достаточно малы", никаких несоответствий не возникнет.
В этом смысле целочисленная арифметика C является заполнителем, который точно не определен по спецификации языка программирования, но полностью создается путем определения целевой машины.
Java точно определяет, как будут представлены целые числа и как должна вычисляться целочисленная арифметика.
Java Integers
--------------------------
Signed | Unsigned
--------------------------
long (64-bit) |
int (32-bit) |
short (16-bit) | char (16-bit)
byte (8-bit) |
Char - единственный целочисленный тип без знака. Его значения представляют символы Unicode, от \u0000
до \uffff
, то есть от 0 до 2 16 -1.
Если целочисленный оператор имеет операнд типа long, то другой операнд также преобразуется в тип long. В противном случае операция выполняется в операндах типа int, при необходимости более короткие операнды преобразуются в int. Правила преобразования точно определены.
[Из электронных заметок в теоретической компьютерной науке 82 № 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER, Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Карлсруэ, Германия]
Ответ 2
EDIT: Хорошо, теперь мы знаем это Java...
Раздел 4.2.2 Спецификации языка Java гласит:
Язык программирования Java обеспечивает ряд операторов, которые действуют интегральные значения:
[...]
Числовые операторы, которые приводят к в значении типа int или long: [...] Аддитивные операторы + и - (§15.18)
Другими словами, он похож на С# - оператор сложения (когда применяется к интегральным типам) только когда-либо приводит к int
или long
, поэтому вам нужно использовать для привязки к переменной short
.
Оригинальный ответ (С#)
В С# (вы не указали язык, поэтому я догадываюсь), единственными операторами добавления в примитивных типах являются:
int operator +(int x, int y);
uint operator +(uint x, uint y);
long operator +(long x, long y);
ulong operator +(ulong x, ulong y);
float operator +(float x, float y);
double operator +(double x, double y);
Они приведены в спецификации С# 3.0, раздел 7.7.4. Кроме того, определено десятичное сложение:
decimal operator +(decimal x, decimal y);
(Здесь также определяются перечисление, конкатенация строк и комбинация делегатов.)
Как вы можете видеть, нет оператора short operator +(short x, short y)
- поэтому оба операнда неявно преобразуются в int и используется форма int. Это означает, что результат представляет собой выражение типа "int", следовательно, необходимо отбрасывать.
Ответ 3
В С# и Java арифметическое выражение в правой части присваивания по умолчанию принимает значение int. Вот почему вам нужно отбросить короткое, потому что нет очевидной причины неявного преобразования int int в короткие сроки.
Ответ 4
Учитывая, что вопрос "почему int по умолчанию" не ответил...
Во-первых, "default" на самом деле не является правильным термином (хотя и достаточно близко). Как отмечено VonC, выражение, состоящее из ints и longs, будет иметь длинный результат. И операция, состоящая из ints/logs и double, будет иметь двойной результат. Компилятор продвигает термины выражения любому типу, который обеспечивает больший диапазон и/или точность результата (предполагается, что типы с плавающей запятой имеют больший диапазон и точность, чем интегральные, хотя вы теряете точность преобразования больших длин, чтобы удвоить).
Одно из предостережений заключается в том, что эта акция происходит только для условий, которые в ней нуждаются. Таким образом, в следующем примере подвыражение 5/4 использует только интегральные значения и выполняется с использованием целочисленной математики, хотя общее выражение включает в себя двойной. Результат не в том, что вы можете ожидать...
(5/4) * 1000.0
ОК, так почему байты и короткие продвигаются до int? Без каких-либо ссылок, чтобы поддержать меня, это из-за практичности: существует ограниченное количество байт-кодов.
"Bytecode", как следует из его названия, использует один байт для указания операции. Например, iadd, который добавляет два ints. В настоящее время 205 опкодов определены, а целочисленная математика принимает 18 для каждого типа (т.е. 36 между целыми и длинными), не считая операторов преобразования.
Если коротко, и каждый байт получил свой собственный набор кодов операций, вы должны быть на уровне 241, что ограничивает возможность расширения JVM. Как я уже сказал, никаких ссылок на это не удалось, но я подозреваю, что Гослинг и др. Говорили, "как часто люди на самом деле используют шорты?" С другой стороны, продвижение байта к int приводит к этому не очень замечательному эффекту (ожидаемый ответ - 96, фактический - -16):
byte x = (byte)0xC0;
System.out.println(x >> 2);
Ответ 5
Какой язык вы используете?
На многих языках на языке C есть правило, что любое математическое выражение выполняется в размере int или больше. Из-за этого, как только вы добавляете два шорта, результат имеет тип int. Это вызывает необходимость в литье.
Ответ 6
Java всегда использует не менее 32 битных значений для вычислений. Это связано с 32-разрядной архитектурой, которая была распространена в 1995 году, когда была введена Java. Размер регистра в ЦП составлял 32 бит, а арифметический логический блок принимал 2 номера длины регистра процессора. Таким образом, cpus был оптимизирован для таких значений.
Вот почему все типы данных, которые поддерживают арифметические операции и имеют меньше 32 бит, преобразуются в int (32 бит), как только вы используете их для вычислений.
Итак, чтобы подвести итог, в основном это было связано с проблемами производительности и в настоящее время поддерживается для совместимости.
Ответ 7
В java каждое числовое выражение типа:
anyPrimitive zas = 1;
anyPrimitive bar = 3;
?? x = zas + bar
x всегда будет иметь по крайней мере значение int или long, если один из добавочных элементов был длинным.
Но есть некоторые причуды жесткие
byte a = 1; // 1 is an int, but it won't compile if you use a variable
a += 2; // the shortcut works even when 2 is an int
a++; // the post and pre increment operator work
Ответ 8
Любой тип данных witch меньше, чем "int" (кроме булева), неявно преобразуется в "int".
В вашем случае:
short a = 2;
short b = 3;
short c = a + b;
результат (a + b) неявно преобразован в int. И теперь вы назначаете его "short". Так что вы получаете ошибку.
short, byte, char - для всех этих ошибок мы получим ту же ошибку.
Ответ 9
AFAIS, никто не упоминает об использовании final
для этого. Если вы измените свой последний пример и определите переменные a и b как final
переменные, то компилятор уверен, что их сумма, значение 5, может быть присвоена
переменная типа byte
, без какой-либо потери точности. В этом случае компилятор хорош
назначить сумму a и b на c. Имеет модифицированный код:
final byte a = 2;
final byte b = 3;
byte c = a + b;
Ответ 10
Я хотел бы добавить что-то, что не было указано. Java не учитывает значения, заданные вами переменными (2 и 3) в...
short a = 2;
короткий b = 3;
short c = a + b;
Итак, насколько известно Java, вы могли бы сделать это...
short a = 32767;
короткий b = 32767;
short c = a + b;
Который был бы вне диапазона коротких, он автоматически выводит результат в int, потому что он "возможно", что результат будет больше, чем короткий, но не более, чем int. Int был выбран как "по умолчанию", потому что в основном большинство людей не будут жесткими значениями кодирования выше 2,147,483,647 или ниже -2,147,483,648