Найти в Дзене
ГАУС IT

Разбираем примитивные типы в Java

Как уже говорилось, существует 8 простых типов данных, которые делятся на целочисленные (integer), дробные (floating-point) и булевские (boolean).
Оглавление

Как уже говорилось, существует 8 простых типов данных, которые делятся на целочисленные (integer), дробные (floating-point) и булевские (boolean).

Целочисленные типы

Целочисленные типы - это byte, short, int, long, также к ним относят и char. Первые четыре типа имеют длину 1, 2, 4 и 8 байт соответственно, длина char - 2 байта, что непосредственно следует из того, что все символы Java описываются стандартом Unicode. Длины типов приведены только для оценки областей значения. Как уже говорилось, память в Java представляется виртуальной, и вычислить, сколько физических ресурсов займет та или иная переменная так прямолинейно не получится.

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

Инициализировать его можно как символьным, так и целочисленным литералом. Во всем остальном char - полноценный числовой тип данных, который может участвовать, например, в арифметических действиях, операциях сравнения и т.п. На в таблице сведены данные по всем разобранным типам:

-2

Обратите внимание, что 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 байт соответственно. Оба типа знаковые.

В таблице сведены их характеристики:

-3

Для целочисленных типов область значений задавалась верхней и нижней границами, весьма близкими по модулю. Для дробных типов добавляется еще одно ограничение - насколько можно приблизиться к нулю, другими словами - каково наименьшее положительное ненулевое значение. Таким образом, нельзя задать литерал заведомо больший, чем позволяет соответствующий тип данных, это приведет к ошибке 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.

Если статья была Вам полезна, ставьте пальцы вверх и подписывайтесь. Оставляйте свои пожелания и вопросы в комментариях, с удовольствием отвечу.

Часть 1

#it #java для новичков #программирование #с нуля