Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Типы данных Основы Java

Число в виде строки

Внутри высокоуровневых языков программирования данные разделяются по типам. Например, строки относятся к типу String, а числа — к типу int.

Зачем нужны типы? Для защиты программы от трудноотловимых ошибок. Типы определяют две вещи:

  • Допустимые значения. Например, числа в Java делятся на две группы типов: целые int и рациональные float. Такое разделение связано с техническими особенностями работы аппаратуры.
  • Набор допустимых операций. Например, операция умножения имеет смысл для типа «целые числа». Но не имеет смысла для типа «строки»: умножать слово «мама» на слово «блокнот» — бессмыслица.

Язык программирования распознает типы. Поэтому Java не позволит нам умножать строку на строку. Но позволит умножать целое число на другое целое число. Наличие типов и таких ограничений в языке защищает программы от случайных ошибок:

"one" * "two"
Error:
bad operand types for binary operator '*'
    first type:  java.lang.String
    second type: java.lang.String

Каким образом Java понимает, что за тип данных перед ним? Любое значение где-то инициализируется. В зависимости от способа инициализации, становится понятно, что именно находится перед нами.

Например, число — это просто число, не обернутое в кавычки или другие парные символы. А вот строки всегда ограничены двойными кавычками. Например, значение "234"считается строкой, хотя внутри нее записаны цифры:

// Компилятор понимает что тут число
var age = 33;

По-английски строки в программировании называются strings, а строчки текстовых файлов называются lines. Например, в коде выше одна строчка (lines) и ноль строк (strings). В русском языке иногда может быть путаница, поэтому во всех уроках мы будем говорить использовать такие термины:

  • Строка — для обозначения типа данных strings
  • Строчка — для обозначения lines (строчек в текстовых файлах)

Типов данных в Java много, плюс можно создавать свои. Постепенно мы познакомимся со всеми необходимыми и научимся их правильно использовать.

Явная типизация

До сих пор при определении переменных мы использовали ключевое слово var, что может удивить тех, кто имеет какой-то опыт на Java. Обычно определение переменных показывают так:

int x = 3;
String greeting = "Hello Hexlet!";

// Error: incompatible types: java.lang.String cannot be converted to int
int ops = "test";

Пришло время раскрыть карты! Java — это статически типизированный язык. В таких языках тип переменной фиксируется при ее объявлении. В большинстве языков для этого перед именем переменной указывается ее тип — в примере выше это число (int) и строка (String).

Раньше на Java создавали переменные только так, до тех пор пока не появился var. var – специальное ключевое слово, которое включает механизм вывода типов. Вывод типов автоматически определяет тип присваиваемого значения и связывает его с переменной. В примерах выше очевидно, где какой тип, тогда зачем его явно прописывать?

Вывод типов в Java появился в 2018 году, но в некоторых других язык он существует не один десяток лет. Первый язык с выводом типов называется ML и появился он аж в 1973 году. С тех пор вывод типов был добавлен в Ocaml, Haskell, C#, F#, Kotlin, Scala и множество других языков.

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

Какие бывают типы

В этом уроке мы рассмотрим систему типов в Java с высоты птичьего полета, не погружаясь в детали. Но сначала ответим на вопрос, зачем вообще про них знать?

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

С другой стороны, не пытайтесь запомнить всю эту информацию про типы наизусть — она дается лишь для общего представления. Все важное о типах вы и так выучите в процессе программирования. Глобально, типы данных в Java делятся на две большие группы:

  • Примитивные — предопределены в Java
  • Ссылочные или не примитивные — создаются самим программистом, за исключением String и Array

У этих групп есть различия, которые мы разберем позже, когда познакомимся с null и объектно-ориентированным программированием. Пока достаточно знать, что имена примитивных типов начинаются с нижнего регистра (int), а ссылочных с верхнего (String).

Всего в Java восемь примитивных типов данных:

  • byte
  • short
  • int
  • long
  • float
  • double
  • boolean
  • char

Рассмотрим первые четыре типа. Это целые числа разного размера:

  • byte — занимает в памяти 1 байт, значит может хранить числа от -128 до 127
  • short — занимает в памяти 2 байта
  • int — занимает в памяти 4 байта
  • long — занимает в памяти 8 байт

Посмотрим на примере такого кода:

byte x = 3; // Отработает без проблем

// Error: incompatible types: possible lossy conversion from int to byte
byte y = 270;

Определение переменной y завершилось с ошибкой, потому что мы указали тип byte, но присвоили переменной значение 270, которое выходит за множество допустимых значений.

Возникает закономерный вопрос. Зачем аж четыре типа для хранения чисел? Почему бы не сделать один, в который влезает почти любое большое число?

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

Такая же логика использовалась для типов float и double. Они оба отвечают за рациональные числа. Разница лишь в том, что double — это двойной float, то есть в памяти он занимает в два раза больше места.

Создатели Java полагаются на разумность программистов, на их способность правильно подобрать нужные типы в зависимости от задачи. Для каких-то экстремальных приложений так и происходит, но в типичной разработке все просто. Программисты выбирают int для целых чисел и double для рациональных.

Рассмотрим оставшиеся типы данных.

Тип boolean отвечает за логические значения true и false. Им посвящен целый раздел, там мы про него и поговорим.

Особняком стоит тип char — символ. Это не строка, у него другой способ определения — через одиночные кавычки:

char ch = 'a';

// Error: incompatible types: java.lang.String cannot be converted to char
char ch2 = "b";

Строка, состоящая из одного символа — это не символ. Кажется, нелогично, но с точки зрения типов все так и должно быть, со временем вы это прочувствуете.

Извлечение символа из строки извлекает как раз символ, а не строку, состоящую из одного символа:

"hexlet".charAt(1); // 'e'

Хорошо, а где тип данных String — строка? Дело в том, что она не является примитивным типом. Внутри она представляет собой массив символов. Несмотря на это техническое различие, строки используются наравне с примитивными типами без особых отличий.

Значение по умолчанию

Примитивные данные всегда имеют значение, даже если они определяются без инициализации:

int a;
System.out.println(a); // => 0

У каждого примитивного типа есть свое значение по умолчанию:

byte    0
short   0
int     0
long    0
float   0.0
double  0.0
char    ''
boolean false

Значение null

Особняком в Java стоит значение null. В Java оно не является типом. Это просто конкретное значение со специальным смыслом и логикой работы. Начнем с примера:

// Определение переменной без инициализации значением
// С var такое не сработает, так как невозможно вывести тип
String a;

Что находится внутри переменной a? Если мы ее распечатаем, то увидим null. Значение null используется для ссылочных типов, когда значение не определено.

Как такое возможно? Представьте, что мы хотим извлечь из базы данных пользователя, а его там нет. Что вернет нам запрос в базу? Вот именно для таких ситуаций и нужен null.

Их гораздо больше, чем может показаться на первый взгляд. Чем дальше мы будем двигаться, тем чаще он начнет встречаться:

var user = // тут делаем запрос в базу
// Если данных нет, то user станет null
// Запись выше равносильна
var user = null;

Из вышесказанного следует важный вывод. Любой ссылочный тип данных может принимать значение null. То есть, null является значением любого ссылочного типа. А вот примитивные типы и null не совместимы. Примитивное значение всегда должно быть определено:

// Error: incompatible types: <nulltype> cannot be converted to int
int x = null;

Явное преобразование типов

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

Данные формы всегда приходят в текстовом виде, даже если значение число. Вот как его можно преобразовать:

// станет int
var number = Integer.parseInt("345");
System.out.println(number); // => 345

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

var result = (int) 5.1;
System.out.println(result); // => 5

Преобразование типов можно использовать внутри составных выражений:

// Дополнительные скобки помогают визуально отделить части выражения друг от друга
var result = 10 + ((int) 5.1);
System.out.println(result); // => 15

https://replit.com/@hexlet/java-basics-data-types


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Java-разработчик
Профессия
с нуля
Разработка приложений на языке Java
2 февраля 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»