Тип данных определяет:
- множество (диапазон) значений, которые могут принимать величины этого
типа (которые может хранить переменная или константа)
- операции, которые могут выполняться над величинами этого типа
- внутреннее представление данных в памяти компьютера
Размер типов данных остается неизменным на всех платформах (стандартизирован).
Java - строго типизированный (не динамический) язык программирования. Это означает, что тип данных каждой переменной и выражений задается заранее и известен при компилировании.
При выполнении операции присваивания переменной значения выражения, переменная и выражение должны быть одного типа (проверка этого выполняется компилятором, что значительно упрощает поиск ошибок и приводит к повышению надежности программы).
Все типы исходных данных, встроенные в язык Java, делятся на две группы:
- примитивы - примитивные (то есть не делимые на более мелкие) типы
- ссылки - (непримитивные) (сложные) типы
Также выделяют ссылочные типы данных, для которых в ячейке памяти содержится не сами данные, а только адреса этих данных, то есть ссылки на данные.
Примитивные типы Java
При выполнении операции присваивания для переменных, имеющих примитивный тип, выполняется копирование данных из одной ячейки памяти в другую.
Примитивными являются логический тип boolean, целые числовые типы byte, short, int, long, char и плавающие числовые типы float и double.
Непримитивные (сложные) типы Java
Сложные (непримитивные типы данных) образуются из простых путём группировки.
Переменные примитивных типов хранят в себе значения, а переменные типов-классов хранят ссылку на объекты этого же класса, или null (если ссылка не задана).
Например, String (Строка) - сложный, непримитивный тип данных, хранящий свои данные в виде таблицы символов, где каждый символ таблицы - это примитивный тип char.
Рис. 1 Схема классификации типов данных
Примитивные типы данных
Среди примитивных типов данных выделяют четыре типа для целочисленных
значений (byte, short, int и long), два типа для дробных данных с плавающей точкой (float и double), один тип данных для символов (char) и один тип данных для логических условий true и false (boolean).
В таблице ниже приведены все примитивные типы данных и их характеристики:
Здесь Size - разрядность (количество байтов, выделяемых для хранения значений типа в оперативной памяти)
Example Literals - диапазон значений.
Если требуется создать ссылку на один из примитивных типов данных, необходимо использовать соответствующий класс-обертку. Оборачивание примитива в объект называется упаковкой (boxing), а обратный процесс распаковкой (unboxing).
Соответствие типов данных классам-оберткам:
byte соответсвует Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean
• byte:
хранит целое число
диапазон значений: от -128 до 127
занимает 1 байт
значение по умолчанию 0
• short
хранит целое число
диапазон значений: от -32768 до 32767
занимает 2 байта
значение по умолчанию 0
• int
хранит целое число
диапазон значений: от -2147483648 до 2147483647
занимает 4 байта
значение по умолчанию 0
• long
хранит целое число
диапазон значений: от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
занимает 8 байт
значение по умолчанию 0L (используйте заглавную букву, что бы не спутать букву с единицей)
(По умолчанию, java интерпретирует все целочисленные переменные как 32-битные значения типа integer.
Если нужноуказать, что используется тип long, нужно добавлять суффикс L в конце значения.
Помимо десятичной системы счисления, можно применять и другие. К примеру:
Помимо десятичной системы счисления, можно применять и другие. К примеру:
int u = 0x6F; // 16-иричная система, число 111
(Для задания шестнадцатеричного значения после символов 0x указывается число в шестнадцатеричном формате)
int u = 010; // 8-иричная система, число 8
(Для задания восьмеричного значения после символа 0 указывается число в восьмеричном формате)
int u13 = 0b1101; // 2-иричная система, число 13 .
(Для задания двоичного значения после символов 0b указывается число в двоичном формате)
Также целые числа поддерживают разделение разрядов числа с помощью знака подчеркивания:
int x = 123_456; int y = 234_567__789;
System.out.println(x); // 123456 System.out.println(y); // 234567789
При делении целочисленных данных остаток отбрасывается.
Тип данных с плавающей точкой
Вещественные числа могут быть представлены в двух форматах:
- с фиксированной точкой – совпадает с обычной математической записью десятичного числа с дробной частью, в качестве разделителя целой и дробной части в дробных литералах используется точка.
- с плавающей точкой – применяется при записи очень больших или
очень малых чисел. В этом формате число, стоящее перед символом
«E», умножается на число 10 в степени, указанной после символа «E».
Значения вещественных типов в компьютере представляются приближенно и определяются двумя типами:
• double
хранит число с плавающей точкой
диапазон значений: от ±4.9*10^-324 до ±1.8*10^308
занимает 8 байт
значение по умолчанию 0.0D (с двойной точностью - 17 цифр)
• float
• float
хранит число с плавающей точкой
диапазон значений: от -3.4*10^38 до 3.4*10^38
занимает 4 байта; Значение по умолчанию 0.0F (с одинарной точностью - 7-8 цифр)
*для точных операций, например с деньгами, нижеперечисленные типы
данных использовать не рекомендуется - используйте, например, BigDecimal.
При присвоении переменной типа float дробного литерала с плавающей точкой, например, 3.1, 4.5 и т.д., Java автоматически рассматривает этот литерал как значение типа double.
Чтобы указать, что данное значение должно рассматриваться как float, нам надо использовать суффикс f: float fl = 30.6f; double db = 30.6;
В данном случае обе переменных имеют практически одно значение, но эти значения будут по-разному рассматриваться и будут занимать разное место в памяти.
К обычным вещественным числам добавляются еще три значения:
- положительная бесконечность, выражаемая константой POSITIVE_INFINITY и возникающая при переполнении положительного значения
- отрицательная бесконечность, выражаемая константой NEGATIVE_INFINITY и возникающая при переполнении отрицательного значения
- «не число», выражаемое константой NaN (Not a Number) и возникающее при делении вещественного числа на нуль или умножении нуля на бесконечность.
Кроме того, спецификация языка Java различает положительный и отрицательный нули (+0.0 и -0.0), возникающие при делении на бесконечность соответствующего знака.
Логический тип данных boolean
• boolean: хранит значение 'true' или 'false'; Значение по умолчанию 'false'.
boolean isActive = false;
boolean isAlive = true;
char sex='m';
boolean isSexM = 'm' == 1; //В результате isSexM = true;
boolean isSexM = 'm' == 1; //В результате isSexM = true;
Типы boolean и integer в языке Java несовместимы между собой.
В отличие от языков C и C++, в Java константа true не равна 1, а константа false не равна 0.
В отличие от языков C и C++, в Java константа true не равна 1, а константа false не равна 0.
Тип текстовых данных
• char:
хранит одиночный символ в кодировке UTF-16 (символ представлен в 16-битным значением в Unicode-таблице) и поэтому занимает 2 байта
диапазон его хранимых значений от 0 до 65535, что позволяет использовать 65536 различных символов
значение по умолчанию ‘\ u0000’
Unicode – это стандарт кодирования символов, который позволяет предоставить знаки всех языков мира. Поскольку Java использует набор символов UNICODE он поддерживает интернационализацию.
В качестве значения переменная символьного типа получает одиночный символ, заключенный в ординарные кавычки:
Еще одной формой задания символьных переменных является шестнадцатеричная форма: переменная получает значение в шестнадцатеричной форме, которое следует после символов '\u'.
char ch='e';
Кроме того, переменной символьного типа также можно присвоить целочисленное значение от 0 до 65536. В этом случае переменная опять же
будет хранить символ, а целочисленное значение будет указывать на номер символа в таблице символов Unicode (UTF-16).Еще одной формой задания символьных переменных является шестнадцатеричная форма: переменная получает значение в шестнадцатеричной форме, которое следует после символов '\u'.
(Код любого символа в кодировке Unicode набирается в апострофах после обратной наклонной черты и латинской буквы u четырьмя шестнадцатеричными
цифрами.)
Таким образом, можно закодировать все символы Unicode последовательностями от \u0000 до \uFFFF.
Например, если в программу нужно вставить знак с кодом 6917, необходимо его представить в шестнадцатеричном формате (1B05) и записать это значение как \u1B05, причем буква u должна быть строчной, а шестнадцатеричные цифры A, B, C, D, E, F можно использовать как заглавные, так и строчные.
Пример: char ch='\u0066'; будет хранить символ 'f'.
Символьные переменные не стоит путать со строковыми: здесь 'a' не идентично "a".
Строковые переменные представляют объект String, который в отличие от char или int не является примитивным типом в Java: String hello = "Hello..."; System.out.println(hello);
Тип char является псевдоцелочисленным типом, поэтому значения этого типа можно задавать в виде числа - кода символа из таблицы кодировки UTF-16. Каждому символу соответствует определённое число из таблицы и Java при виде этого числа в рамках типа char выводит его на экран как символ. То есть, например, при выполнении кода
char c2 = 97;
System.out.println(c2);
на консоль выведется
a.
Ссылочные типы данных
Ссылочными типами называются типы данных, для которых в ячейке памяти содержится не сами данные, а только адреса этих данных, то есть ссылки на данные.
К ссылочным типам относятся классы, интерфейсы и массивы.
Существует также специальный нулевой тип – это зарезервированное слово null, обозначающее нулевой адрес.
Свойства ссылочного типа данных:
- при выполнении операции присваивания в ссылочную переменную заносится адрес данных, а не сами данные
- непосредственный доступ к адресу, хранящемуся в ссылочных переменных, в языке Java отсутствует
- ссылки можно присваивать друг другу, только если они совместимы по типам
- если переменной ссылочного типа не присвоено значение (ещё нет ссылки на какой-то объект), в ней хранится значение null – специальная «пустая ссылка».
В этом случае переменная просто хранит адрес объекта равный 0, но так как Java-машина никогда не создаёт объекты с таким адресом, распознает,
что если переменная-ссылка содержит 0, то никакого объекта там нет.
- ссылочным переменным можно присваивать значение null (пустую (нулевую) ссылку):
b=null;
b=null;
Приведение примитивных типов данных
(преобразование выражения одного типа данных к выражению другого типа данных)
Рис.2 Схема совместимости типов данных
Здесь: сплошные линии указывают на преобразования без потери данных - с расширением, штриховые линии - на операции с возможной потерей
данных, сужающие.
Случай 1) Преобразование с расширением (conversion):
переменная меньшей ёмкости назначается другой переменной большей ёмкости. (автоматическое преобразование)
Например, от типа byte к типу int.
В данном случае конфликта не происходит (такие преобразования безопасны) и операции выполняются автоматически, без дополнительных указаний: новый тип всегда гарантированно вмещает в себя все данные, которые хранились в старом типе, и таким образом не происходит потери данных.
Поэтому компилятор осуществляет это преобразование сам и никакихспециальных действий для этого
предпринимать не требуется.
Расширяющими являются следующие преобразования:
- от byte к short, int, long, float, double
- от short к int, long, float, double
- от char к int, long, float, double
- от int к long, float, double
- от long к float, double
- от float к double
Случай 2) Преобразование сужающее (type casting):
переменная большей ёмкости назначается другой переменной меньшей ёмкости. (явное преобразование типов)
В данном случае может произойти конфликт и данные могут быть потеряны.
В Java такое преобразование должно совершаться явным образом,
т.е.программист в коде должен явно указать, что он намеревается
осуществить такое преобразование и готов идти на потерю данных.
Операция явного преобразования типов предполагает указание перед переменной или выражением в скобках того типа, к которому надо преобразовать значение. Например, если написать(byte) перед значением типа int, мы в качестве результата получим значение типа byte
Следующие преобразования являются сужающими:
- от byte к char
- от short
к byte, char
- от char к byte, short
- от int к byte, short, char
- от long
к byte, short, char, int
- от float к byte, short, char, int, long
- от double
к byte, short, char, int, long, float
Сужающие преобразования проводят, например, если оперируемое значение можно отнести к обоим рассматриваемым типам данных.
Если же размер целочисленной части слишком велик для присваиваемого типа, то значение будет уменьшено до результата деления по модулю на диапазон целевого типа.
( Также сужающие преобразования выполняют с усечением: когда число с
плавающей точкой приводят к целочисленному типу с отбрасыванием при этом
хвостовой (дробной) части.)
Для дробных типов (float и double) сужение (приведение такого числа к целочисленному типу) происходит с отбрасыванием у него дробной части.
При выполнении операций с переменными, имеющими различные типы данных, тип каждого операнда и результата автоматически повышается до типа с наибольшей ёмкостью; при этом тип данных переменной, которой присваивается результирующее значение должен соответствовать ёмкости результата или же должно использоваться явное приведение.
Пример потери данных при сужающем пребразовании:
Изначальное значение, хранящееся в переменной типа int - 10000000. Она занимает 32 бита памяти.
При записи этого значения в переменную типа short, которая может хранить только 16 бит, происходит следующее: только первые 16 бит вышеуказанного числа будут туда перемещены, остальные - отбросятся, не производится округления или каких-либо других действий для получения более корректного результата.
Примечания:
Объявление и инициализация переменных
Чтобы объявить переменную, для неё необходимо указать тип данных и присвоить ей уникальное имя.
Пример объявления типа данных:
int a;
Также можно комбинировать объявление переменных и их инициализацию:
char b='m';
Пример операции с ссылочными (сложными) переменными:
ТипПеременной имяПеременной = ссылка на новосозданный объект вида (( new ТипСоздаваемогоОбъекта(); ))
Okras okras=new Okras();
*использованы материалы с сайтов:
https://guru99.ru/java-variables/
https://www.geeksforgeeks.org/data-types-in-java/
https://java-master.com/primitive-types-of-data-in-java/
https://javarush.ru/groups/posts/630-primitivnihe-tipih-v-java--ne-takie-uzh-oni-i-primitivnihe