Как уже говорилось, существует 8 простых типов данных, которые делятся на целочисленные (integer), дробные (floating-point) и булевские (boolean).
Целочисленные типы
Целочисленные типы - это byte, short, int, long, также к ним относят и char. Первые четыре типа имеют длину 1, 2, 4 и 8 байт соответственно, длина char - 2 байта, что непосредственно следует из того, что все символы Java описываются стандартом Unicode. Длины типов приведены только для оценки областей значения. Как уже говорилось, память в Java представляется виртуальной, и вычислить, сколько физических ресурсов займет та или иная переменная так прямолинейно не получится.
4 основных типа являются знаковыми. char добавлен к целочисленным типам данных, так как с точки зрения JVM символ и его код - взаимно однозначные понятия. Конечно, код символа всегда положительный, поэтому char - единственный без знаковый тип.
Инициализировать его можно как символьным, так и целочисленным литералом. Во всем остальном char - полноценный числовой тип данных, который может участвовать, например, в арифметических действиях, операциях сравнения и т.п. На в таблице сведены данные по всем разобранным типам:
Обратите внимание, что int вмещает примерно 2 миллиарда, а потому подходит во многих случаях, когда не требуются сверхбольшие числа. Чтобы представить себе размеры типа long, укажем, что именно он используется в Java для отсчета времени. Как и во многих языках, время отсчитывается от 1 января 1970 года в миллисекундах. Так вот, вместимость long позволяет отсчитывать время на протяжении миллионов веков(!), причем как в будущее, так и в прошлое.
Почему было обращено внимание именно на эти два типа, int и long? Дело в том, что целочисленные литералы имеют тип int по умолчанию или тип long, если стоит буква L или l. Именно поэтому корректным литералом считается только такое число, которое укладывается в 4 или 8 байт соответственно. Иначе компилятор сочтет это ошибкой.
Над целочисленными аргументами можно производить следующие операции:
- операции сравнения (возвращают булевское значение)
- <, <=, >, >= - ==, !=
- числовые операции (возвращают числовое значение)
- унарные операции + и -
- арифметические операции +, -, *, /, %
- операции инкремента и декремента (в префиксной и постфиксной форме): ++ и --
- операции битового сдвига << , >>, >>>
- битовые операции ~, & , |, ^
- оператор с условием ? :
- оператор приведения типов
- оператор конкатенации со строкой +
Операторы сравнения вполне очевидны и особого рассмотрения не требуют. Их результат всегда булевского типа (true или false).
Работа числовых операторов также понятна. Единственное уточнение можно сделать относительно операторов + и -, которые могут быть как бинарными (иметь два операнда), так и унарными (иметь один операнд). Бинарные операнды являются операторами сложения и вычитания соответственно. Унарный оператор
+ возвращает значение, равное аргументу (+x всегда равно x). Унарный оператор -,
примененный к значению x, возвращает результат, равный 0-x. Неожиданный эффект
происходит в случае, если аргумент равен наименьшему возможному значению примитивного типа.
int x=-2147483648; // Наименьшее возможное значение типа int
int y=-x;
Теперь значение переменной y наc самом деле равно не 2 147 483 648, поскольку такое число не укладывается в область значений типа int, а в точности равно значению x! Другими словами в этом примере выражение -x==x истинно!
Дело в том, что если при выполнении числовых операций над целыми числами возникает переполнение, и результат не может быть сохранен в данном примитивном типе, то Java не создает никаких ошибок. Вместо этого все старшие биты, которые превышают вместимость типа, просто отбрасываются. Это может привести не только к потере точной абсолютной величины результата, но и даже к искажению его знака, если на месте знакового бита окажется противоположное значение.
int x= 300000;
print(x*x);
Результатом такого примера будет:
-194 313 216
Для каждого примитивного типа существуют специальные вспомогательные классы-обертки. Для типов byte, short, int, long, char это Byte, Short, Integer, Long, Character. Эти классы содержат многие полезные методы для работы с целочисленными значениями. Например, преобразование из текста в число. Кроме этого, есть класс Math, который хоть и предназначен в основном для работы с дробными числами, но также предоставляет некоторые возможности и для целых.
В заключение подчеркнем, что единственные операции с целыми числами, при которых Java генерирует ошибки - это деление на ноль (операторы / и %)
Дробные типы
Дробные типы - это float и double. Их длины - 4 и 8 байт соответственно. Оба типа знаковые.
В таблице сведены их характеристики:
Для целочисленных типов область значений задавалась верхней и нижней границами, весьма близкими по модулю. Для дробных типов добавляется еще одно ограничение - насколько можно приблизиться к нулю, другими словами - каково наименьшее положительное ненулевое значение. Таким образом, нельзя задать литерал заведомо больший, чем позволяет соответствующий тип данных, это приведет к ошибке overflow. И нельзя задать литерал, значение которого по модулю слишком мало для данного типа, компилятор сгенерирует ошибку underflow.
// пример вызовет ошибку компиляции
float f = 1e40f; // значение слишком велико, overflow
double d = 1e-350; // значение слишком мало, underflow
Напомним, что если в конце литерала стоит буква F или f, то литерал рассматривается как значение типа float. По умолчанию дробный литерал имеет тип double, при желании это можно подчеркнуть буквой D или d.
Над дробными аргументами можно производить следующие операции:
- операции сравнения (возвращают булевское значение)
- <, <=, >, >= - ==, !=
- числовые операции (возвращают числовое значение)
- унарные операции + и -
- арифметические операции +, -, *, /, %
- операции инкремента и декремента (в префиксной и постфиксной форме): ++ и --
- оператор с условием ? :
- оператор приведения типов
- оператор конкатенации со строкой +
Практически все операторы действуют по тем же принципам, что и для целочисленных операторов.
Уточним лишь, что операторы сравнения корректно работают и в случае сравнения целочисленных значений с дробными. Таким образом, в основном необходимо рассмотреть вопросы переполнения и преобразования типов при вычислениях.
Для дробных вычислений появляется уже два типа переполнения - overflow и underflow.
Тем не менее, Java и здесь никак не сообщает о возникновении подобных ситуаций. Нет ни ошибок, ни других способов обнаружить их. Более того, даже деление на ноль не приводит к некорректной ситуации. А значит, дробные вычисления вообще не порождают никаких ошибок.
Такая свобода связана с наличием специальных значений дробного типа. Они определяются спецификацией IEEE 754:
- положительная и отрицательная бесконечности (positive/negative infinity);
- значение "не число", Not-a-Number, или сокращенно NaN;
- положительный и отрицательный нули.
Все эти значения представлены как для типа float, так и для double.
Положительную и отрицательную бесконечности можно получить следующим образом:
1f/0f // положительная бесконечность, тип float
-1d/0d // отрицательная бесконечность, тип double
Также в классах Float и Double определены константы POSITIVE_INFINITY и NEGATIVE_INFINITY. Как видно из примера, такие величины получаются при делении конечных величин на ноль.
Значение NaN можно получить, например, в результате следующих действий:
0.0/0.0 // деление ноль на ноль
(1.0/0.0)*0.0 // умножение бесконечности на ноль
Эта величина также представлена константами NaN в классах Float и Double.
Величины положительный и отрицательный ноль записываются очевидным образом:
0.0 // дробный литерал со значением положительного нуля
+0.0 // унарная операция +, ее значение - положительный ноль
-0.0 // унарная операция -, ее значение - отрицательный ноль
Все дробные значения строго упорядочены. Отрицательная бесконечность меньше любого другого дробного значения, положительная - больше. Значения +0.0 и -0.0 считаются равными, то есть выражение 0.0==-0.0 истинно, а 0.0>-0.0 - ложно. Однако другие операторы различают их, например, выражение 1.0/0.0 дает положительную бесконечность, а 1.0/- 0.0 - отрицательную.
Единственное исключение - значение NaN. Если хотя бы один из аргументов операции сравнения равняется NaN, то результат заведомо будет false. Таким образом, единственное значение x, при котором выражение x!=x истинно, именно NaN.
Для каждого примитивного типа существуют специальные вспомогательные классы-обертки (wrapper classes). Для типов float и double это Float и Double. Эти классы содержат многие полезные методы для работы с дробными значениями. Например, преобразование из текста в число.
Кроме этого, класс Math предоставляет большое количество методов для операций над дробными значениями, например, извлечение квадратного корня, возведение в любую степень, тригонометрические и другие. Также в этом классе определены константы PI и основание натурального логарифма E.
Булевский тип
Булевский тип представлен всего одним типом boolean, который может хранить всего два возможных значения - true и false. Величины именно этого типа получаются в результате операций сравнения.
Над булевскими аргументами можно производить следующие операции:
- операции сравнения (возвращают булевское значение)
- ==, !=
- логические операции (возвращают булевское значение)
- !
- &, |, ^
- &&, ||
- оператор с условием ? :
- оператор конкатенации со строкой +
В операторе с условием ? : первым аргументом может быть только значение типа boolean. Также допускается, чтобы второй и третий аргументы одновременно также имели булевский тип.
Операция конкатенации со строкой превращает булевскую величину в текст "true" или "false" в зависимости от значения.
Только булевские выражения допускаются для управления потоком вычислений, например, в качестве критерия условного перехода if.
Никакое число не может быть интерпретировано как булевское выражение. Если предполагается, что ненулевое значение эквивалентно истине, то необходимо записать x!=0. Ссылочные величины можно преобразовывать к boolean выражением ref!=null.
Если статья была Вам полезна, ставьте пальцы вверх и подписывайтесь. Оставляйте свои пожелания и вопросы в комментариях, с удовольствием отвечу.
#it #java для новичков #программирование #с нуля