Поиск…


Вступление

8 примитивных типов данных byte , short , int , long , char , boolean , float и double - это типы, которые хранят большинство исходных числовых данных в Java-программах.

Синтаксис

  • int aInt = 8; // Определяющая (числовая) часть этого объявления int называется литералом.

  • int hexInt = 0x1a; // = 26; Вы можете определить литералы с шестнадцатеричными значениями с префиксом 0x .

  • int binInt = 0b11010; // = 26; Вы также можете определить бинарные литералы; с префиксом 0b .

  • long goodLong = 10000000000L; // По умолчанию целочисленные литералы имеют тип int. Добавив L в конец литерала, вы сообщаете компилятору, что литерал длинный. Без этого компилятор будет вызывать ошибку «Целое число слишком большое».

  • double aDouble = 3,14; // Литералы с плавающей запятой по умолчанию имеют тип double.

  • float aFloat = 3.14F; // По умолчанию этот литерал был бы двойным (и вызвал ошибку «Несовместимые типы»), но, добавив F, мы скажем компилятору, что это float.

замечания

Java имеет 8 примитивных типов данных , а именно: boolean , byte , short , char , int , long , float и double . (Все остальные типы являются ссылочными типами, включая все типы массивов и встроенные типы объектов / классы, которые имеют особое значение на языке Java, например String , Class и Throwable и его подклассы).

Результат всех операций (сложение, вычитание, умножение и т. Д.) В примитивном типе - это, по меньшей мере, int , поэтому добавление short в short вызывает int , как и добавление byte в byte , или char для char , Если вы хотите присвоить результат этого значения значению того же типа, вы должны его бросить. например

byte a = 1;
byte b = 2;
byte c = (byte) (a + b);

Неисполнение операции приведет к ошибке компиляции.

Это связано со следующей частью Java Language Spec, §2.11.1 :

Компилятор кодирует нагрузки буквенных значений byte типов и short с помощью инструкций Java Virtual Machine, которые подписывают эти значения до значений типа int во время компиляции или времени выполнения. Загрузка значений букв типов boolean и char кодируется с использованием инструкций, которые нулевым образом расширяют литерал до значения типа int во время компиляции или времени выполнения. [..]. Таким образом, большинство операций над значениями фактических типов boolean , byte , char и short корректно выполняются инструкциями, действующими на значения вычислительного типа int .

Причина этого также указана в этом разделе:

Учитывая однобайтовый размер кода операции Java Virtual Machine, типы кодирования в opcodes оказывают давление на дизайн своего набора команд. Если каждая типизированная команда поддерживает все типы данных во время выполнения Java Virtual Machine, будет больше инструкций, чем может быть представлено в byte . [...] Отдельные инструкции могут использоваться для преобразования между неподдерживаемыми и поддерживаемыми типами данных по мере необходимости.

Int примитив

Примитивный тип данных, такой как int содержит значения непосредственно в переменной, которая его использует, между тем переменная, которая была объявлена ​​с использованием Integer содержит ссылку на значение.

Согласно java API : «Класс Integer обертывает значение примитивного типа int в объекте. Объект типа Integer содержит одно поле, тип которого является int».

По умолчанию int представляет собой 32-разрядное целое число со знаком. Он может хранить минимальное значение -2 31 и максимальное значение 2 31 - 1.

int example = -42;
int myInt = 284;
int anotherInt = 73;

int addedInts = myInt + anotherInt; // 284 + 73 = 357
int subtractedInts = myInt - anotherInt; // 284 - 73 = 211

Если вам нужно сохранить номер за пределами этого диапазона, следует использовать его в качестве long . Превышение диапазона значений int приводит к переполнению целых чисел, в результате чего значение, превышающее диапазон, будет добавлено к противоположному сайту диапазона (положительное становится отрицательным и наоборот). Значение равно ((value - MIN_VALUE) % RANGE) + MIN_VALUE или ((value + 2147483648) % 4294967296) - 2147483648

int demo = 2147483647; //maximum positive integer
System.out.println(demo); //prints 2147483647
demo = demo + 1; //leads to an integer overflow
System.out.println(demo); // prints -2147483648

Максимальное и минимальное значения int можно найти по адресу:

int high = Integer.MAX_VALUE;    // high == 2147483647
int low = Integer.MIN_VALUE;     // low == -2147483648

Значение по умолчанию для int равно 0

int defaultInt;    // defaultInt == 0

Короткий примитив

short является 16-разрядное целое число со знаком. Он имеет минимальное значение -2 15 (-32,768), а максимальное значение составляет 2 15 -1 (32 767)

short example = -48;
short myShort = 987;
short anotherShort = 17;

short addedShorts = (short) (myShort + anotherShort); // 1,004
short subtractedShorts = (short) (myShort - anotherShort); // 970

Максимальные и минимальные значения short можно найти по адресу:

short high = Short.MAX_VALUE;        // high == 32767
short low = Short.MIN_VALUE;         // low == -32768

Значение по умолчанию short равно 0

short defaultShort;    // defaultShort == 0

Длинный примитив

По умолчанию long - это 64-разрядное целое число со знаком (в Java 8 оно может быть либо подписано, либо без знака). Подписано, оно может хранить минимальное значение -2 63 и максимальное значение 2 63 - 1, а без знака оно может хранить минимальное значение 0 и максимальное значение 2 64 - 1

long example = -42;
long myLong = 284;
long anotherLong = 73;

//an "L" must be appended to the end of the number, because by default,
//numbers are assumed to be the int type. Appending an "L" makes it a long
//as 549755813888 (2 ^ 39) is larger than the maximum value of an int (2^31 - 1),
//"L" must be appended 
long bigNumber = 549755813888L;

long addedLongs = myLong + anotherLong; // 284 + 73 = 357
long subtractedLongs = myLong - anotherLong; // 284 - 73 = 211

Максимальное и минимальное значения long можно найти по адресу:

long high = Long.MAX_VALUE;    // high == 9223372036854775807L
long low = Long.MIN_VALUE;     // low == -9223372036854775808L

Значение по умолчанию long равно 0L

long defaultLong;    // defaultLong == 0L

Примечание: буква «L», добавленная в конце long литерала, нечувствительна к регистру, однако хорошей практикой является использование капитала, поскольку ее легче отличить от цифры один:

2L == 2l;            // true

Предупреждение: Java кэширует объекты Integer объектов из диапазона от -128 до 127. Объяснение здесь объясняется: https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof

Следующие результаты можно найти:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2); // true

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4); // false

Чтобы правильно сравнить значения 2 объекта Long, используйте следующий код (начиная с Java 1.7):

Long val3 = 128L;
Long val4 = 128L;

System.out.println(Objects.equal(val3, val4)); // true

Сравнение примитива long long с Object long не приведет к ложному отрицанию, сравнив 2 объекта с.

Булевский примитив

boolean может сохранять одно из двух значений: true или false

boolean foo = true;
System.out.println("foo = " + foo);                // foo = true

boolean bar = false;
System.out.println("bar = " + bar);                // bar = false

boolean notFoo = !foo;
System.out.println("notFoo = " + notFoo);          // notFoo = false

boolean fooAndBar = foo && bar;
System.out.println("fooAndBar = " + fooAndBar);    // fooAndBar = false

boolean fooOrBar = foo || bar;
System.out.println("fooOrBar = " + fooOrBar);      // fooOrBar = true

boolean fooXorBar = foo ^ bar;
System.out.println("fooXorBar = " + fooXorBar);    // fooXorBar = true

Значение по умолчанию для boolean равно false

boolean defaultBoolean;    // defaultBoolean == false

Байт-примитив

byte представляет собой 8-разрядное целое число со знаком. Он может хранить минимальное значение -2 7 (-128), а максимальное значение 2 7 - 1 (127)

byte example = -36;
byte myByte = 96;
byte anotherByte = 7;

byte addedBytes = (byte) (myByte + anotherByte); // 103
byte subtractedBytes = (byte) (myBytes - anotherByte); // 89

Максимальное и минимальное значения byte можно найти по адресу:

byte high = Byte.MAX_VALUE;        // high == 127
byte low = Byte.MIN_VALUE;         // low == -128

Значение по умолчанию byte равно 0

byte defaultByte;    // defaultByte == 0

Поплавковый примитив

float - это 32-битное число с плавающей запятой IEEE 754 с одной точностью. По умолчанию десятичные знаки интерпретируются как двойные. Чтобы создать float , просто добавьте f в десятичный литерал.

double doubleExample = 0.5;      // without 'f' after digits = double
float floatExample = 0.5f;       // with 'f' after digits    = float

float myFloat = 92.7f;           // this is a float...
float positiveFloat = 89.3f;     // it can be positive,
float negativeFloat = -89.3f;    // or negative
float integerFloat = 43.0f;      // it can be a whole number (not an int)
float underZeroFloat = 0.0549f;  // it can be a fractional value less than 0

Поплавки обрабатывают пять общих арифметических операций: сложение, вычитание, умножение, деление и модуль.

Примечание. В результате ошибок с плавающей запятой могут незначительно отличаться. Некоторые результаты были округлены для ясности и удобочитаемости (т. Е. Напечатанный результат примера добавления был фактически 34.600002).

// addition
float result = 37.2f + -2.6f;  // result: 34.6

// subtraction
float result = 45.1f - 10.3f;    // result: 34.8

// multiplication
float result = 26.3f * 1.7f;   // result: 44.71

// division
float result = 37.1f / 4.8f;   // result: 7.729166

// modulus
float result = 37.1f % 4.8f;   // result: 3.4999971

Из-за того, что хранятся числа с плавающей точкой (т. Е. В двоичной форме), многие числа не имеют точного представления.

float notExact = 3.1415926f;
System.out.println(notExact); // 3.1415925

Хотя использование float подходит для большинства приложений, для хранения точных представлений десятичных чисел (например, денежных сумм) или чисел, где требуется более высокая точность, не следует использовать float или double . Вместо этого следует использовать класс BigDecimal .

Значение по умолчанию для float равно 0.0f .

float defaultFloat;    // defaultFloat == 0.0f

float точностью до ошибки составляет 1 из 10 миллионов.

Примечание: Float.POSITIVE_INFINITY , Float.NEGATIVE_INFINITY , Float.NaN - значения с float . NaN означает результаты операций, которые невозможно определить, например, деление 2 бесконечных значений. Кроме того, 0f и -0f различны, но == дает true:

float f1 = 0f;
float f2 = -0f;
System.out.println(f1 == f2); // true
System.out.println(1f / f1); // Infinity
System.out.println(1f / f2); // -Infinity
System.out.println(Float.POSITIVE_INFINITY / Float.POSITIVE_INFINITY); // NaN

Двойной примитив

double - это 64-битное число с плавающей запятой IEEE 754 с двойной точностью.

double example = -7162.37;
double myDouble = 974.21;
double anotherDouble = 658.7;

double addedDoubles = myDouble + anotherDouble; // 315.51
double subtractedDoubles = myDouble - anotherDouble; // 1632.91

double scientificNotationDouble = 1.2e-3;    // 0.0012

Из-за того, что хранятся числа с плавающей запятой, многие номера не имеют точного представления.

double notExact = 1.32 - 0.42; // result should be 0.9
System.out.println(notExact); // 0.9000000000000001

Хотя для большинства приложений используется double для хранения точных чисел, таких как валюта, не следует использовать ни float ни double . Вместо этого следует использовать класс BigDecimal

Значение по умолчанию double равно 0.0d

public double defaultDouble;    // defaultDouble == 0.0

Примечание: Double.POSITIVE_INFINITY , Double.NEGATIVE_INFINITY , Double.NaN - double значения. NaN означает результаты операций, которые невозможно определить, например, деление 2 бесконечных значений. Кроме того, 0d и -0d различны, но == -0d true:

double d1 = 0d;
double d2 = -0d;
System.out.println(d1 == d2); // true
System.out.println(1d / d1); // Infinity
System.out.println(1d / d2); // -Infinity
System.out.println(Double.POSITIVE_INFINITY / Double.POSITIVE_INFINITY); // NaN

Первоначальный символ

char может хранить один 16-разрядный символ Юникода. Символьный литерал заключен в одинарные кавычки

char myChar = 'u';
char myChar2 = '5';
char myChar3 = 65; // myChar3 == 'A'

Он имеет минимальное значение \u0000 (0 в десятичном представлении, также называемое нулевым символом ) и максимальное значение \uffff (65,535).

Значением по умолчанию char является \u0000 .

char defaultChar;    // defaultChar == \u0000

Чтобы определить значение символа «char ' использовать escape-последовательность (символ, которому предшествует обратная косая черта):

char singleQuote = '\'';

Существуют также другие escape-последовательности:

char tab = '\t';
char backspace = '\b';
char newline = '\n';
char carriageReturn = '\r';
char formfeed = '\f';
char singleQuote = '\'';
char doubleQuote = '\"'; // escaping redundant here; '"' would be the same; however still allowed
char backslash = '\\';
char unicodeChar = '\uXXXX' // XXXX represents the Unicode-value of the character you want to display

Вы можете объявить char любого символа Юникода.

char heart = '\u2764';
System.out.println(Character.toString(heart)); // Prints a line containing "❤".

Также можно добавить char . например, для повторения каждой строчной буквы, вы можете сделать следующее:

for (int i = 0; i <= 26; i++) {
    char letter = (char) ('a' + i);
    System.out.println(letter);
}

Представление отрицательного значения

Java и большинство других языков хранят отрицательные целые числа в представлении , обозначаемом дополнением 2 .

Для уникального двоичного представления типа данных с использованием n бит значения кодируются следующим образом:

Наименее значимые n-1 биты сохраняют положительное целое число x в интегральном представлении. Наиболее значимое значение хранит бит с значением s . Значение, представленное этими битами, равно

x - s * 2 n-1

т.е. если самый старший бит равен 1, то значение, которое просто на 1 больше, чем число, которое вы могли бы представить с другими битами ( 2 n-2 + 2 n-3 + ... + 2 1 + 2 0 = 2 n-1 - 1 ), что дает уникальное двоичное представление для каждого значения от - 2 n-1 (s = 1; x = 0) до 2 n-1 - 1 (s = 0; x = 2 n-1 - 1).

Это также имеет хороший побочный эффект, что вы можете добавить двоичные представления, как если бы они были положительными двоичными числами:

v1 = x1 - s1 * 2n-1
v2 = x2 - s2 * 2n-1
s1 s2 переполнение x1 + x2 результат добавления
0 0 нет x1 + x2 = v1 + v2
0 0 да слишком большой, чтобы быть представленным типом данных (переполнение)
0 1 нет
x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1
= v1 + v2
0 1 да
(x1 + x2) mod 2n-1 = x1 + x2 - 2n-1
= v1 + v2
1 0 * см. выше (сменные слагаемые)
1 1 нет слишком мал, чтобы быть представленным типом данных (x1 + x2 - 2 n <-2 n-1 , underflow)
1 1 да
(x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1
= (x1 - s1 * 2n-1) + (x2 - s2 * 2n-1)
= v1 + v2

Обратите внимание, что этот факт упрощает поиск двоичного представления аддитивного обратного (т. Е. Отрицательного значения):

Обратите внимание, что добавление побитового дополнения к числу приводит к тому, что все биты равны 1. Теперь добавьте 1, чтобы сделать переполнение значения, и вы получите нейтральный элемент 0 (все биты 0).

Таким образом, отрицательное значение числа i можно вычислить, используя (игнорируя возможную рекламу для int здесь)

(~i) + 1

Пример: принятие отрицательного значения 0 ( byte ):

Результатом отрицания 0 является 11111111 . Добавление 1 дает значение 100000000 (9 бит). Поскольку byte может хранить только 8 бит, самое левое значение усекается, а результат равен 00000000

оригинал Процесс Результат
0 (00000000) сводить на нет -0 (11111111)
11111111 Добавить 1 в двоичный 100000000
100000000 Усекать до 8 бит 00000000 (-0 равно 0)

Потребление памяти примитивов против бокс-примитивов

Примитивный В штучной упаковке Размер памяти примитива / в штучной упаковке
логический логический 1 байт / 16 байт
байт Байт 1 байт / 16 байт
короткая короткий 2 байта / 16 байт
голец голец 2 байта / 16 байт
ИНТ целое число 4 байта / 16 байт
долго Долго 8 байт / 16 байт
поплавок терка 4 байта / 16 байт
двойной двойной 8 байт / 16 байт

Объектам в штучной упаковке всегда требуется 8 байтов для управления типом и памятью, а так как размер объектов всегда кратен 8, для всех типов в штучной упаковке требуется всего 16 байтов . Кроме того , каждое использование объекта в штучной упаковке влечет за собой хранение ссылки, которая учитывает еще 4 или 8 байтов, в зависимости от параметров JVM и JVM.

В операциях с интенсивным использованием данных потребление памяти может существенно повлиять на производительность. Потребление памяти растет еще больше при использовании массивов: для массива float[5] требуется только 32 байта; тогда как Float[5] хранящий 5 различных ненулевых значений, потребует всего 112 байтов (на 64-разрядном без сжатых указателей, это увеличивается до 152 байт).

Вложенные кеширование значений

Косвенные накладные расходы в штучной упаковке могут быть в некоторой степени смягчены кэшами в штучной упаковке. Некоторые из типов в штучной упаковке реализуют кеш экземпляров. Например, по умолчанию класс Integer будет кэшировать экземпляры для представления чисел в диапазоне от -128 до +127 . Однако это не снижает дополнительные затраты, связанные с дополнительной памятью.

Если вы создаете экземпляр типа boxed либо с помощью autoboxing, либо путем вызова статического метода valueOf(primitive) , система времени выполнения попытается использовать кешированное значение. Если ваше приложение использует множество значений в кэше, то это может существенно снизить штраф за использование ящиков в коробке. Конечно, если вы создаете экземпляры экземпляров в штучной упаковке «вручную», лучше использовать valueOf вместо new . ( new операция всегда создает новый экземпляр.) Если, однако, большинство ваших значений не находятся в кешированном диапазоне, быстрее можно вызвать new и сохранить поиск кеша.

Преобразование примитивов

В Java мы можем конвертировать между целыми значениями и значениями с плавающей запятой. Кроме того, поскольку каждый символ соответствует числу в кодировке Unicode, типы char могут быть преобразованы в типы и с целыми числами и с плавающей точкой. boolean - единственный примитивный тип данных, который не может быть преобразован в какой-либо другой примитивный тип данных.

Существует два типа конверсий: расширение конверсии и сужение конверсии .

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

Соответственно, сужение преобразования - это когда значение одного типа данных преобразуется в значение другого типа данных, который занимает меньше битов, чем первый. В этом случае может произойти потеря данных.

Java автоматически расширяет конверсии . Но если вы хотите выполнить сужение конверсии (если вы уверены, что потеря данных не произойдет), вы можете заставить Java выполнить преобразование с использованием языковой конструкции, известной как cast .

Расширение конверсии:

int a = 1;    
double d = a;    // valid conversion to double, no cast needed (widening)

Сужение конверсии:

double d = 18.96
int b = d;       // invalid conversion to int, will throw a compile-time error
int b = (int) d; // valid conversion to int, but result is truncated (gets rounded down)
                 // This is type-casting
                 // Now, b = 18

Примитивные типы

Таблица, показывающая диапазон размеров и значений всех примитивных типов:

тип данных числовое представление диапазон значений значение по умолчанию
логический н / ложный и истинный ложный
байт 8-разрядная подписка -2 7 до 2 7 - 1 0
От -128 до +127
короткая 16-разрядная подписка -2 15 - 2 15 - 1 0
-32,768 до +32,767
ИНТ 32-разрядная подписка -2 31 до 2 31 - 1 0
-2,147,483,648 до +2,147,483,647
долго 64-битная подпись -2 63 до 2 63 - 1 0L
-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807
поплавок 32-битная с плавающей запятой 1.401298464e-45 до 3.402823466e + 38 (положительный или отрицательный) 0.0f
двойной 64-битная плавающая точка 4.94065645841246544e-324d до 1.79769313486231570e + 308d (положительный или отрицательный) 0.0d
голец 16-разрядный беззнаковый 0 до 2 16 - 1 0
0 до 65535

Заметки:

  1. Спецификация языка Java предусматривает, что подписанные интегральные типы ( byte через long ) используют двоичное представление двухкомпонента, а типы с плавающей точкой используют стандартные двоичные представления с плавающей точкой IEE 754.
  2. Java 8 и более поздние версии предоставляют методы для выполнения беззнаковых арифметических операций по int и long . Хотя эти методы позволяют программе обрабатывать значения соответствующих типов как неподписанные, типы остаются подписанными типами.
  3. Наименьшая плавающая точка, показанная выше, является субнормальной ; т.е. они имеют меньшую точность, чем нормальное значение. Наименьшие нормальные числа: 1.175494351e-38 и 2.2250738585072014e-308
  4. char обычно представляет собой блок кода Unicode / UTF-16.
  5. Хотя boolean содержит только один бит информации, его размер в памяти варьируется в зависимости от реализации виртуальной машины Java (см. Boolean type ).


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow