1. Список примітивних типів

У Java є 8 базових примітивних типів. Примітивними їх називають тому, що значення цих типів не є об'єктами та зберігаються безпосередньо всередині змінних.

У цій таблиці наведено коротку інформацію про ці типи:

Тип Розмір,
байт
Діапазон значень Значення за замовчуванням Опис
byte 1 -128 .. 127 0 Найменше ціле — 1 байт
short 2 -32,768 .. 32,767 0 Коротке ціле, 2 байти
int 4 -2*109 .. 2*109 0 Ціле число, 4 байти
long 8 -9*1018 .. 9*1018 0L Довге ціле, 8 байтів
float 4 -1038 .. 1038 0.0f Дробове, 4 байти
double 8 -10308 .. 10308 0.0d Дробове подвійної довжини, 8 байтів
boolean 1 true, false false Логічний тип (тільки true і false)
char 2 0 .. 65,535 '\u0000' Символи, 2 байти, завжди більші за 0
Значення за замовчуванням

До речі, є важливий нюанс. Якщо оголосити змінну класу (поле класу) або статичну змінну класу, але не присвоїти їй жодного значення, вона ініціалізується значенням за замовчуванням. Перелік таких значень наведено в таблиці.

Локальні змінні методів не мають значень за замовчуванням, і якщо ви не присвоїли такій змінній жодного значення, вона вважається неініціалізованою, і використовувати її значення не можна.

Але повернімося до примітивних типів і розгляньмо їх докладніше.



2. Цілі типи

У мові Java є аж 4 цілих типи: byte, short, int і long. Вони відрізняються між собою за розміром і діапазоном значень, які можуть зберігати.

Тип int

Найчастіше використовується тип int. Його назва походить від Integer (цілий). Всі цілочислові літерали в коді мають тип int (якщо до числа не додано літеру L, F або D).

Змінні цього типу можуть мати значення від -2 147 483,648 до +2 147 483,647.

Це досить багато, вистачає майже на всі випадки. Майже всі функції, що повертають число, повертають саме число типу int.

Приклади:

Код Пояснення
int n = "Рядок".length();
Метод length() повертає довжину рядка.
String[] array = {"Tik", "Tak", "Toe"};
int n = array.length;
Поле length містить довжину масиву.

Тип short

Тип short отримав свою назву від short int. Його ще називають коротке ціле. На відміну від типу int, його довжина всього два байти, а можливий діапазон значень — від -32768 до +32767.

Тобто в ньому навіть число мільйон не збережеш. Навіть 50 тисяч. Цей цілочисловий тип використовується в Java рідше за всіх. Його використовують, головним чином, тоді, коли хочуть заощадити пам'ять.

Припустімо, вам заздалегідь відомо, що значення, з якими ви працюєте, не перевищують 30 тисяч, і таких значень мільйони.

Наприклад, ви пишете програму, яка обробляє зображення надвисокої чіткості: на один колір припадає 10 біт. А точок у вашому зображенні — мільйон. Отут таки має значення, який тип використовувати — int чи short.

Тип long

Цей тип отримав свою назву від long int — його ще називають довге ціле. На відміну від типу int, у нього просто гігантський діапазон значень: від -9*1018 до +9*1018.

Чому ж він не є основним цілим типом?

Річ у тім, що мова Java з'явилася ще в середині 90-х, коли більшість комп'ютерів були 32-розрядними. А це означало, що всі процесори були налаштовані на роботу з числами довжиною 32 біти. З цілими числами довжиною 64 біти процесори вже вміли працювати, але операції з ними виконувалися повільніше.

Отож програмісти розумно вирішили зробити стандартним цілим типом тип int, ну а тип long використовувати лише тоді, коли без нього дійсно не обійтися.

Тип byte

Це найменший цілочисловий тип у Java, але його досить часто використовують. Його назва збігається зі словом byte — мінімальною адресованою коміркою пам'яті в Java.

Діапазон допустимих значень типу byte не дуже великий: від -128 до +127. Проте його сила не в цьому. Тип byte найчастіше використовується тоді, коли потрібно зберігати в пам'яті великий блок знеособлених даних. Масив типу byte просто ідеально підходить для таких цілей.

Наприклад, вам потрібно кудись скопіювати файл.

Вам не потрібно обробляти вміст файлу: ви просто хочете створити область пам'яті (буфер), скопіювати в неї вміст файлу, а потім записати ці дані з буфера в інший файл. Масив типу byte — саме те, що для цього потрібно.

Тим більше, що в змінній-масиві зберігається тільки посилання на область пам'яті. Коли значення цієї змінної потрібно передати до якогось методу, передається тільки її адреса в пам'яті, а сам блок пам'яті не копіюється.

byte[] buffer = new byte[1024*1024];
FileInputStream sourceFile = new FileInputStream("c:\\data.txt");
FileOutputStream destFile = new FileOutputStream("c:\\output.txt");
while (true)
{
   int size = sourceFile.read(buffer);   // читаємо дані з файлу в буфер
   destFile.write(buffer, 0, size);      // записуємо дані з буфера у файл

   // припиняємо копіювання, якщо буфер заповнено не до кінця
   if (size < buffer.length) break;
}
sourceFile.close();
destFile.close();


3. Дійсні типи

Серед примітивних типів також є два дійсних. Проте це не зовсім точна назва. Офіційно вони називаються числами з рухомою крапкоюfloating point numbers. Назва походить зі стандарту, де роздільником цілої та дробової частин визначено крапку (не кому).

Корисно

У кожній країні свої стандарти запису чисел (а ви й не знали!).

Дехто звик використовувати точку як роздільник груп розрядів, а кому — для відділення дробової частини: наприклад, мільйон цілих і 153 тисячних можна записати як 1.000.000,153. А от у США, де мешкали творці Java, діє інший стандарт: 1,000,000.153

У мові Java є два примітивних типи з рухомою крапкою: double і float.

Як ми вже казали, ці типи всередині влаштовані особливим чином: фактично кожна змінна цих типів — це не одне число, а два.

Наприклад, дробове число 987654.321 можна представити як 0.987654321*106. Тому в пам'яті воно буде представлене як два числа 987654321 (мантиса — значуща частина числа) і 6 (експонента — степінь десяти).

Тип float

Назва типу float походить від терміна floating point number. Розмір цього типу зовсім невеликий — всього 4 байти (32 біти), але він може зберігати значення від -3.4*1038 до 3.4*1038. Мантиса займає 24 біти, а експонента — 8 бітів. Цей тип здатний зберігати всього 8 значущих цифр.

Такий підхід дає змогу зберігати набагато більші числа, ніж int, використовуючи ті самі 4 байти. Натомість ми жертвуємо точністю. Частина пам'яті витрачається на зберігання мантиси, тому такі числа зберігають лише 6-7 знаків після десяткової коми, інші знаки відкидаються.

Приклад:

Код Значення змінної
float a = (float) 123.456789;
123.45679
float a = (float) 12345.9999;
12346.0
float a = (float) -123.456789E-2;
-1.2345679

Як бачите, основний недолік цього типу — дуже мала кількість значущих цифр і втрата точності вже у восьмій цифрі. Тому тип float не користується особливою популярністю серед Java-програмістів.

Тип double

Тип double — це стандартний тип чисел із рухомою крапкою. Його назва походить від double floating point. Його також називають числом із рухомою крапкою подвійної точності. Усі дійсні літерали за замовчуванням мають тип double.

Цей тип займає 8 байтів пам'яті (64 біти) і може зберігати значення від -1.7*10308 до 1.7*10308. Важливий момент: його мантиса займає 53 біти, а решту 11 біт — експонента.

Це дає змогу зберігати 15–17 значущих цифр.

Приклад:

Код Значення змінної
double a = 1234567890.1234567890;
1234567890.1234567
double a = 1234567890.1234512345;
1234567890.1234512
double a = 1234567890.1357913579;
1234567890.1357913

Така точність, особливо як порівняти з типом float, є визначальною: 99 % усіх операцій із дійсними числами виконуються з типом double.

Для експоненти виділяється 11 бітів, що дає змогу зберігати степінь десяти від -323 до +308 (степінь числа два — від -1024 до +1023). Тип double може легко зберігати числа із сотнею нулів після десяткової коми.

Код Значення змінної
double a = 2E-300 * 3E+302
600.0


4. Нескінченність

Числа з рухомою крапкою мають ще одну цікаву особливість: вони дозволяють зберігати спеціальне значення, яке позначає нескінченність. Причому існують як додатна нескінченність, так і від'ємна нескінченність.

Приклади:

Код Примітка
System.out.println( 100.0 / 0.0 );
Infinity
System.out.println( -100.0 / 0.0 );
-Infinity
double a = 1d / 0d;
double b = a * 10;
double c = b - 100;
a == Infinity
b == Infinity
c == Infinity

Якщо нескінченність помножити на число, отримаємо нескінченність. Якщо до нескінченності додати число, отримаємо нескінченність. Дуже зручно.

Не число (NaN)

Результатом будь-яких операцій із нескінченністю буде нескінченність. Здебільшого — так. Але не завжди.

Числа з рухомою крапкою можуть зберігати ще одне спеціальне значення — NaN. Це є скороченням від Not a Number (не число).

У математиці, якщо поділити нескінченність на нескінченність, виникає невизначеність.

Проте в мові Java результатом ділення нескінченності на нескінченність буде NaN.

Приклади:

Код Примітка
System.out.println(0.0 / 0.0);
NaN
double infinity = 1d / 0d;
System.out.println(infinity / infinity);

NaN
double a = 0.0 / 0.0;
double b = a * 10;
double c = b - 100;
double d = a + infinity;
a == NaN
b == NaN
c == NaN
d == NaN

Результатом будь-якої операції з NaN буде NaN.



5. Тип char

Серед примітивних типів у Java є ще один, вартий особливої уваги, — тип char. Його назва походить від слова Character, а сам тип використовується для зберігання символів.

А символи — це саме те, з чого складаються рядки: кожен рядок є масивом символів.

Проте ще цікавіше, що тип char — це водночас числовий тип! Так би мовити, тип подвійного призначення.

Річ у тім, що насправді тип char зберігає не символи, а коди символів у кодуванні Unicode. Кожному символу відповідає число — числовий код символу.

Кожна змінна типу char займає в пам'яті два байти (так само, як і тип short). Однак на відміну від типу short, цілочисловий тип char — беззнаковий і може зберігати значення від 0 до 65535.

Тип char — це гібридний тип. Його значення можна інтерпретувати і як числа (їх можна складати й множити), і як символи. Так зробили через те, що, хоча символи й мають візуальне подання, для комп'ютера вони насамперед просто числа. І працювати з ними як з числами значно зручніше.

Unicode

Unicode — це спеціальна таблиця (кодування), в якій містяться всі символи світу. І кожен символ має свій номер. Ось ця таблиця (приблизний вигляд):

Примітивні типи в Java

Присвоїти значення змінній типу char можна різними способами.

Код Опис
char a = 'A';
Змінна а міститиме латинську літеру А.
char a = 65;
Змінна а міститиме латинську літеру А. Її код саме 65.
char a = 0x41;
Змінна а міститиме латинську літеру А.
Її код саме 65, що відповідає коду 41 у шістнадцятковій системі.
char a = 0x0041;
Змінна а міститиме латинську літеру А.
Її код саме 65, що відповідає коду 41 у шістнадцятковій системі.
Два зайві нулі не змінюють значення.
char a = '\u0041';
Змінна а міститиме латинську літеру А.
Ще один спосіб задати символ за допомогою його коду.

Найчастіше символ просто вказують у лапках (як у першому рядку таблиці). Проте останній спосіб теж досить поширений. Він має ту перевагу, що його можна використовувати в рядках.

І як вже було сказано, тип char — це водночас цілочисловий тип, тому можна використовувати такий запис:

Код Виведення на екран
char a = 'A';
a++;
System.out.println(a);
На екран буде виведено латинську літеру В. Тому що:
A65
B66
C67

Робота з типом char

Кожний символ char — це насамперед число (код символу), а потім уже символ. Якщо знати код символу, його завжди можна отримати в програмі. Приклад:

Код Виведення на екран
char c = (char) 1128;
System.out.println(c);

Ѩ

Стандартні коди

У цій таблиці наведено найвідоміші коди символів:

Символи Коди
0, 1, 2, ... 9 48, 49, 50, ... 57
a, b, c, ... z 97, 98, 99, ... 122
A, B, C, ... Z 65, 66, 67, ... 90


6. Тип boolean

І останній примітивний тип — це boolean.

Як ви вже знаєте, він може набувати лише двох значень: true і false.

Власне, ви вже знаєте про цей тип усе, що можна.