Java start
Поняття синтаксису та семантики мов програмування
Змінні, типи даних, вирази та привласнення значень змінним
Подання даних у пам'яті комп'ютера: біти, байти тощо.
Найпростіше введення/виведення
Умовні конструкції та їх різновиди
Ітеративні конструкції (цикли)
Методи
JAVA (вимовляється Джава) – об'єктноорієнтована мова програмування, яка розроблена компанією Sun Microsystems (надалі придбаною компанією Oracle)
Джеймс Гослінг (англ. James Gosling; 19 травня 1955 року, Калгарі, Канада) – автор об'єктноорієнтованої та кросплатформної мови програмування Java. Крім цього, він є творцем віконної системи News, Gosling Emacs, а також був одним з розробників Star Seven.
Використовуючи мову Java, можна створювати такі програми:
• настільні застосунки;
• web-застосунки;
• web-сервіси;
• програми для мобільних пристроїв;
• ігри;
• рішення для бізнесу;
• програми для мікроконтролерів та аплети для смарткарт;
• інтерактивний контент для Blu-ray.
Java Runtime Environment (JRE) – для роботи – мінімальна реалізація віртуальної машини, яка необхідна для виконання Java-застосунків, без компілятора й інших засобів розробки. Складається з віртуальної машини – Java Virtual Machine та бібліотеки Java-класів.
Java Development Kit (JDK) – для програмування – безоплатно розповсюджуваний комплект розробника застосунків на мові Java, який вміщує компілятор Java (javac), стандартні бібліотеки класів Java, приклади, документацію, різні утиліти та виконавчу систему Java (JRE).
Java Virtual Machine (Java VM, JVM) – віртуальна машина Java – основна частина виконувальної системи Java, так званої Java Runtime Environment (JRE). Віртуальна машина Java інтерпретує байткод Java, який попередньо створений із вихідного тексту Java-програми компілятором Java (javac). JVM також може використовуватися для виконання програм, написаних іншими мовами програмування.
• JRE необхідний для запуску Java-програм (містить у собі JVM).
• JDK необхідний для розробки (це компілятор, налагоджувач тощо).
• JDK та JRE містять JVM, яка потрібна для запуску програм на Java.
• JVM є серцем мови програмування Java та забезпечує незалежність від платформи.
Integrated development environment
• Eclipse
• IntelliJ IDEA
• NetBeans
Синтаксис мови програмування - набір правил, що описує комбінації символів алфавіту, які вважаються правильно структурованою програмою (документом) або її фрагментом. Синтаксису мови протиставляється його семантика. Синтаксис мови визначає «чисту» мову, у той самий час семантика приписує значення (дії) різним синтаксичним конструкціям.
Кожна мова програмування має синтаксичний опис як частину граматики. Синтаксис мови можна описати, наприклад, за допомогою правил Бекус - Наура.
Синтаксис перевіряється на ранніх стадіях трансляції. В мовах програмування, що інтерпретуються, перевірка синтаксису проводиться або в процесі інтерпретації (виконання), або в процесі попередньої компіляції в проміжний код. Крім того, синтаксис може перевірятися безпосередньо під час редагування вихідних текстів програм під час використання IDE.
Змінна — названа або адресована іншим способом область пам'яті, адресу якої можна використовувати для здійснення доступу до даних. Дані, що перебувають у змінній (тобто за цією адресою пам'яті), називаються значенням цієї змінної.
Статична та динамічна типізація змінних
Якщо тип даних визначається на етапі компіляції, має місце статична типізація, і якщо на етапі виконання програми — динамічна. Іноді кажуть, змінна немає типу, хоча дані, які у ній, безумовно, відносяться до певного типу даних, але з'ясовується це вже під час виконання програми.
У більшості випадків статична типізація дозволяє зменшити витрати ресурсів при виконанні програми, оскільки для динамічної типізації потрібні витрати ресурсів на з'ясування типів даних та їх приведення у виразах зі змішаними типами. Статична типізація дозволяє проводити перевірку типів на етапі компіляції програми. Це також спрощує виявлення помилок ще на етапі розробки, коли їхнє виправлення обходиться менш дорого.
Проте, часто необхідно застосування динамічної типізації. Наприклад, необхідність підтримки сумісності при переході на новий формат представлення даних (наприклад, стара частина проекту надсилає процедурі дату символьним рядком, а нові об'єкти використовують більш сучасний числовий тип).
Статичні та динамічні змінні
Адреса поіменованого осередку пам'яті також може визначатися як на етапі компіляції, так і під час виконання програми. За часом створення змінні бувають статичними та динамічними. Перші створюються на момент запуску програми чи підпрограми, а другі створюються у процесі виконання програми.
Динамічна адресація потрібна лише тоді, коли кількість даних, що надходять, на зберігання, заздалегідь невідомо. Такі дані розміщують у спеціальних динамічних структурах, тип яких вибирається відповідно до специфіки завдання та з можливостями обраної системи програмування. Це може бути стек, купа, черга тощо. Навіть файл, у тому сенсі, який заклав Н.Вірт у Паскаль, є динамічною структурою.
Локальні та глобальні змінні. Області видимості
По зоні видимості розрізняють локальні та глобальні змінні. Перші доступні лише конкретній підпрограмі, другі – всій програмі. З поширенням модульного та об'єктного програмування з'явилися ще й загальні змінні (доступні для певних рівнів ієрархії підпрограм). Область видимості іноді задається класом пам'яті. Обмеження видимості може здійснюватися шляхом запровадження просторів імен.
Обмеження зони видимості придумали як для можливості використовувати однакові імена змінних (що розумно, коли в різних підпрограмах змінні виконують схожу функцію), так і для захисту від помилок, пов'язаних з неправомірним використанням змінних (щоправда, для цього програміст повинен володіти та користуватися відповідною логікою структуризації даних).
Прості та складні змінні
За наявності внутрішньої структури, змінні може бути простими чи складними (складовими).
Прості змінні не мають внутрішньої структури, доступної для адресації. Останнє застереження важливе тому, що для компілятора або процесора змінна може бути якою завгодно складною, але конкретна система (мова) програмування приховує від програміста її внутрішню структуру, дозволяючи адресуватися тільки «загалом».
Складні змінні - програміст створює зберігання даних, що мають внутрішню структуру. Відповідно є можливість звернутися безпосередньо до будь-якого елементу.
Найбільш характерними прикладами складних типів є масив (всі елементи однотипні) та запис (елементи можуть мати різний тип).
Слід підкреслити відносність такого поділу: для різних програм одна й та сама змінна може мати різну структуру.
Наприклад, компілятор розрізняє в змінній речовинного типу 4 поля: знаки мантиси і порядку, плюс їх значення, але для програміста, що компілює свою програму, речовинна змінна - єдиний осередок пам'яті, що зберігає речове число.
Змінні – це контейнери для зберігання значень даних.
Java має різні типи змінних, наприклад:
String - зберігає текст, наприклад, «Привіт». Строкові значення укладені у подвійні лапки.
int - зберігає цілі числа без десяткових знаків, наприклад 123 або -123
float - зберігає числа з плаваючою комою з десятковими знаками, наприклад 19,99 або -19,99
char - зберігає окремі символи, такі як 'a' або 'B'. Значення символів поміщені в одинарні лапки.
boolean - зберігає значення з двома станами: true чи false
Створіть змінну myNum типу int і присвойте ей значення 15:
int myNum = 15;
System.out.println(myNum);
Ви також можете пояснити змінну без присвоєння значень і присвоїти значення пiзнiше:
int myNum;
myNum = 15;
Sm.ouystet.println(myNum);
Зверніть увагу, що якщо ви присвоїте нове значення існуючої змінної, воно перепише попереднє значення:
int myNum = 15;
myNum = 20; // myNum is now 20
System.out.println(myNum);
Однак ви можете додати ключове слово final, якщо ви не хочете, щоб інші (або ви) перезаписували наявні значення (це об’єднуватиме змінну як «final» або «постійну», що означає незмінну та доступну тільки для читання)
final int myNum = 15;
myNum = 20; // will generate an error: cannot assign a value to a final variable
int myNum = 5;
float myFloatNum = 5.99f;
char myLetter = 'D';
boolean myBool = true;
String myText = "Hello";
Відображення змінних
Метод println() часто використовується для відображення змінних.
Щоб поєднати і текст, і змінну, використовуйте символ +:
String name = "John";
System.out.println("Hello " + name);
Ви також можете використовувати символ +, щоб додати змінну до іншої змінної:
String firstName = "John ";
String lastName = "Doe";
String fullName = firstName + lastName;
System.out.println(fullName);
Для числових значень символ + працює як математичний оператор (звернiть увагу, що ми використовуємо змінні типу int (цiлi)):
int x = 5;
int y = 6;
D // Print the value of x + y
З наведеного вище прикладу можна очікувати:
x stores the value 5
y stores the value 6
Потім ми використовуємо метод println() для відображення значення x + y, яке дорівнює 11
Щоб об'явити більше однієї змінної одного типу, скористайтеся списком, розділеними комами:
int x = 5, y = 6, z = 50;
System.out.println(x + y + z);
Всі змінні Java повинні мати унікальні імена.
Ці унікальні імена називаються ідентифікаторами.
Ідентифікатори можуть бути короткими іменами (наприклад, x і y) або більш описовими іменами (вік, сума, загальний обсяг).
Примітка: рекомендується використовувати описовi імена для створення зрозумiлого та підтримуваного коду:
// Good
int minutesPerHour = 60;
// OK, but not so easy to understand what m actually is
int m = 60;
Як пояснилося раніше, змінна в Java повинна мати вказаний тип даних:
int myNum = 5; // Integer (whole number)
float myFloatNum = 5.99f; // Floating point number
char myLetter = 'D'; // Character
boolean myBool = true; // Boolean
String myText = "Hello"; // String
Примітивний тип даних визначає розмір і тип значень змінних і не має додаткових методів.
У Java є вісім примітивних типів даних:
Приведення типів
Приведення типів – це коли ви надаєте значення одного примітивного типу даних іншому типу.
У Java існує два типи приведення:
Розширення Casting (автоматично) - перетворення меншого шрифту на більший розмір шрифту
byte -> short -> char -> int -> long -> float -> double
Сужающий Casting (вручную) - преобразование типа большего размера в тип меньшего размера
double -> float -> long -> int -> char -> short -> byte
Розширюється Casting
Розширення приведення виконується автоматично при передачі типу меншого розміру тип більшого розміру:
public class Main {
public static void main(String[] args) {
int myInt = 9;
double myDouble = myInt; // Automatic casting: int to double
System.out.println(myInt); // Outputs 9
System.out.println(myDouble); // Outputs 9.0
}
}
Звуження Casting
Звуження приведення потрібно робити вручну, поміщаючи тип у круглих дужках перед значенням:
public class Main {
public static void main(String[] args) {
double myDouble = 9.78d;
int myInt = (int) myDouble; // Manual casting: double to int
System.out.println(myDouble); // Outputs 9.78
System.out.println(myInt); // Outputs 9
}
}
Примітивні числові типи поділяються на дві групи:
Цілочисленні типи зберігають цілі числа, позитивні чи негативні (наприклад, 123 чи -456), без десяткових знаків. Допустимі типи: byte, short, int і long. Який тип використовувати залежить від числового значення.
Типи з плаваючою комою представляють числа із дробовою частиною, що містить один або кілька десяткових знаків. Є два типи: float та double.
Byte
Тип даних byte може зберігати цілі числа від -128 до 127. Його можна використовувати замість int або інших цілих типів для економії пам'яті, якщо ви впевнені, що значення буде в межах від -128 до 127:
byte myNum = 100;
System.out.println(myNum);
Short
Тип даних short може зберігати цілі числа від -32768 до 32767:
short myNum = 5000;
System.out.println(myNum);
Int
Тип даних int може зберігати цілі числа від -2147483648 до 2147483647. У цілому тип даних int є кращим типом даних, коли ми створюємо змінні з числовим значенням.
int myNum = 100000;
System.out.println(myNum);
Long
Тип даних long може зберігати цілі числа від -9223372036854775808 до 9223372036854775807. Він використовується, коли int недостатньо великий для зберігання значення. Зверніть увагу, що ви повинні закінчити значення літерою «L»:
long myNum = 15000000000L;
System.out.println(myNum);
Floating Point Types
Тип даних з плаваючою комою може зберігати дробові числа від 3,4 e-038 до 3,4 e + 038. Зверніть увагу, що ви повинні закінчити значення літерою «f»:
float myNum = 5.75f;
System.out.println(myNum);
Double
Тип даних double може зберігати дробові числа від 1,7 e-308 до 1,7 e + 308. Зверніть увагу, що ви повинні закінчити значення літерою «d»:
double myNum = 19.99d;
System.out.println(myNum);
Число з плаваючою комою також може бути науковим числом з літерою "e" для позначення ступеня 10:
float f1 = 35e3f;
double d1 = 12E4d;
System.out.println(f1);
System.out.println(d1);
Booleans
Логічний тип даних оголошується за допомогою ключового слова boolean і може набувати лише значення true або false:
boolean isJavaFun = true;
boolean isFishTasty = false;
System.out.println(isJavaFun); // Outputs true
System.out.println(isFishTasty); // Outputs false
Char
Тип даних char використовується для збереження одного символу. Символ повинен бути поміщений в одинарні лапки, наприклад 'A' або 'c':
char myGrade = 'B';
System.out.println(myGrade);
Strings
Тип даних String використовується для збереження послідовності символів (тексту). Строкові значення повинні бути укладені у подвійні лапки:
String greeting = "Hello World";
System.out.println(greeting);
Оператори використовуються для виконання операцій зі змінними та значеннями.
У наведеному нижче прикладі ми використовуємо оператор + для складання двох значень:
int sum1 = 100 + 50; // 150 (100 + 50)
int sum2 = sum1 + 250; // 400 (150 + 250)
int sum3 = sum2 + sum2; // 800 (400 + 400)
Оператори порівняння використовуються для порівняння двох значень:
Клас Java Math має багато методів, які дозволяють виконувати математичні завдання над числами.
Math.max(x,y)
Math.max(5, 10);
Math.min(x,y)
Math.min(5, 10);
Math.sqrt(x)
The Math.sqrt(x) method returns the square root of x:
Math.sqrt(64);
Math.abs(x)
Math.abs(-4.7);
Random Numbers
example
int randomNum = (int)(Math.random() * 101); // 0 to 100
Дуже часто в програмуванні вам знадобиться тип даних, який може мати лише одне з двох значень, наприклад:
YES / NO
ON / OFF
TRUE / FALSE
Для цього Java має логічний тип даних, який може приймати значення true або false.
Булеві значення Javaboolean isJavaFun = true;
boolean isFishTasty = false;
System.out.println(isJavaFun); // Outputs true
System.out.println(isFishTasty); // Outputs false
Boolean Expression
int x = 10;
int y = 9;
System.out.println(x > y); // returns true, because 10 is higher than 9
System.out.println(10 > 9); // returns true, because 10 is higher than 9
У наведених нижче прикладах ми використовуємо оператор рівності (==) для обчислення виразу:
int x = 10;
System.out.println(x == 10); // returns true, because the value of x is equal to 10
System.out.println(10 == 15); // returns false, because 10 is not equal to 15
Використовуйте оператор if, щоб вказати блок коду Java, який буде виконуватись, якщо умова є true.
if (condition) {
// block of code to be executed if the condition is true
}
if (20 > 18) {
System.out.println("20 is greater than 18");
}
Ми також можемо перевірити змінні:
int x = 20;
int y = 18;
if (x > y) {
System.out.println("x is greater than y");
}
Умови Java та оператори If
Java підтримує звичайні логічні умови з математики:
Less than: a < b Менше ніж: a <b
Less than or equal to: a <= b Менше або дорівнює: a <= b
Greater than: a > b Більше ніж: a> b
Greater than or equal to: a >= b Більше або дорівнює: a> = b
Equal to a == b Дорiвнює a == b
Not Equal to: a != b Не дорівнює: a! = B
Java має такі умовні оператори:
Використовуйте if, щоб вказати блок коду, який буде виконано, якщо зазначена умова істинна
Використовуйте else, щоб вказати блок коду, який буде виконано, якщо та сама умова є помилковою
Використовуйте else if, щоб вказати нову умову для перевірки, якщо перша умова хибна
Використовуйте switch, щоб указати багато альтернативних блоків коду для виконання
else твердження
Використовуйте оператор else, щоб вказати блок коду, який буде виконано, якщо умова false.
if (condition) {
// block of code to be executed if the condition is true
} else {
// block of code to be executed if the condition is false
}
int time = 20;
if (time < 18) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}
// Outputs "Good evening."
else if твердження
Використовуйте оператор else if, щоб задати нову умову, якщо перша умова false.
if (condition1) {
// block of code to be executed if condition1 is true
} else if (condition2) {
// block of code to be executed if the condition1 is false and condition2 is true
} else {
// block of code to be executed if the condition1 is false and condition2 is false
}
Example
int time = 22;
if (time < 10) {
System.out.println("Good morning.");
} else if (time < 20) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}
// Outputs "Good evening."
Ви можете просто написати:
int time = 20;
String result = (time < 18) ? "Good day." : "Good evening.";
System.out.println(result);
Використовуйте оператор switch, щоб вибрати один із багатьох блоків коду для виконання.
switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
Ось як це працює:
Вираз switch обчислюється один раз.
Значення виразу порівнюється зі значеннями кожного case.
Якщо є збіг, виконується відповідний блок коду.
У наведеному нижче прикладі використовується номер дня тижня для обчислення назви дня тижня:
int day = 4;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
}
// Outputs "Thursday" (day 4)
Ключове слово break
Коли Java досягає ключового слова break, вона виривається з блоку switch.
Це зупинить виконання додаткового коду та тестування випадків всередині блоку.
Коли збіг знайдено, і робота виконана, настав час break. Більше тестування не потрібно.
break може заощадити багато часу на виконання, оскільки вона "ігнорує" виконання всього іншого коду в блоці комутатора
Ключове слово default визначає деякий код для запуску, якщо немає відповідності регістру:
int day = 4;
switch (day) {
case 6:
System.out.println("Today is Saturday");
break;
case 7:
System.out.println("Today is Sunday");
break;
default:
System.out.println("Looking forward to the Weekend");
}
// Outputs "Looking forward to the Weekend"
Кон'юнкція AND - && Кон'юнкція (від лат. conjunctio – союз, зв'язок) – логічна операція, яка за своїм застосуванням максимально наближена до союзу «і».
Таблиця істинності для операції кон'юнкції двох логічних виразів:
true && true = true
true && false = false
false && false = false
false && true = false
операнд1 && операнд2 = результат
Побітове І – це бінарна операція, дія якої еквівалентна застосуванню логічного І до кожної пари бітів, які стоять на однакових позиціях у двійкових представленнях операндів.
Таблиця істинності для операції побітового «І» (кон'юнкції) значень
1 & 1 = 1 0 & 0 = 0 1 & 0 = 0 0 & 1 = 0
Диз'юнкція (лат. disjunctio – роз'єднання) – логічна операція, яка за своїм застосуванням максимально наближена до союзу «або» в сенсі «або те, або це, або обидва відразу.
операнд1 || операнд2 = результат
Таблиця істинності для операції диз'юнкції двох логічних виразів:
true || true = true
true || false = true
false || false = false
false || true = true
Побітове «АБО» – це бінарна операція, дія якої еквівалентна застосуванню логічного АБО до кожної пари бітів, які стоять на однакових позиціях у двійкових представленнях операндів.
Таблиця істинності для операції побітового «АБО» (диз'юнкції) значень
1 | 1 = 1
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
Виключене АБО (логічне додавання, строга диз'юнкція) – булева функція та логічна операція. Результат виконання операції є дійсним лише за умови, якщо один операнд є дійсним, а інший хибним.
операнд1 ^ операнд2 = результат
Таблиця істинності для операції диз'юнкції двох логічних виразів:
true ^ true = false
true ^ false = true
false ^ false = false
false ^ true = true
Побітове «Виключне АБО» XOR - ^ Побітове виключне АБО – це бінарна операція, дія якої еквівалентна застосуванню логічного виключеного АБО до кожної пари бітів, які стоять на однакових позиціях у двійкових представленнях операндів.
Таблиця істинності для операції побітового «Виключного АБО» значень
1 ^ 1 = 0
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
Заперечення в логіці – унарна операція над судженнями, результатом якої є судження (у певному сенсі) «протилежне» вихідному.
! операнд = результат
Таблиця істинності для операції заперечення логічного виразу:
!false = true !true = false
Запереченням істини є брехня, а запереченням брехні – істина.
Побітове заперечення (НЕ) – це унарна операція, дія якої еквівалентна застосуванню логічного заперечення до кожного біта двійкового уявлення операнда.
Таблиця істинності для операції побітового «Заперечення НЕ» значень
~ 0 = 1
~ 1 = 0 Т
Щоб змінити знак числа, необхідно виконати його заперечення та отриманий результат збільшити на 1.
~ ( +N ) + 1 = -N
~ ( -N ) + 1 = +N
Логічні зсуви числа
Logical shifts - <<, >> Під час логічного зрушення значення останнього біта за напрямком зсуву втрачається (копіюючись у біт перенесення), а перший набуває нульового значення.
253 << 2 = -12
Логічні зсуви числа
Logical shifts - <<, >> Під час логічного зрушення значення останнього біта за напрямком зсуву втрачається (копіюючись у біт перенесення), а перший набуває нульового значення.
-127 >> 2 = -32
Біти, які виходять за межі діапазону, губляться
Цикли можуть виконувати блок коду, доки досягається задана умова.
Цикли зручні, оскільки вони економлять час, зменшують кількість помилок і роблять код більш читабельним.
Цикл while перебирає блок коду, доки виконується задана умова true:
while (condition) {
// code block to be executed
Example
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
Цикл do/while є варіантом циклу while. Цей цикл виконає блок коду один раз, перш ніж перевірити, чи є умова істинною, потім він повторюватиме цикл, доки умова істинна.
do {
// code block to be executed
}
while (condition);
int i = 0;
do {
System.out.println(i);
i++;
}
while (i < 5);
Коли ви точно знаєте, скільки разів ви хочете прокрутити блок коду, використовуйте цикл for замість циклу while:
for (statement 1; statement 2; statement 3) {
// code block to be executed
}
Оператор 1 виконується (один раз) перед виконанням блоку коду.
Оператор 2 визначає умову виконання блоку коду.
Оператор 3 виконується (щоразу) після виконання блоку коду.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
Існує також цикл «for-each», який використовується виключно для перебору елементів у масиві:
for (type variableName : arrayName) {
// code block to be executed
}
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
System.out.println(i);
}
Оператор break також можна використовувати для виходу з циклу.
for (int i = 0; i < 10; i++) {
if (i == 4) {
break;
}
System.out.println(i);
}
Оператор сontinue
Оператор continue перериває одну ітерацію (у циклі), якщо виникає зазначена умова, і продовжує наступну ітерацію в циклі.
for (int i = 0; i < 10; i++) {
if (i == 4) {
continue;
}
System.out.println(i);
}
Ви також можете використовувати break і continue у циклах while:
int i = 0;
while (i < 10) {
System.out.println(i);
i++;
if (i == 4) {
break;
}
}
-------------------
int i = 0;
while (i < 10) {
if (i == 4) {
i++;
continue;
}
System.out.println(i);
i++;
}
Масив – іменований набір однотипних змінних, розташованих у пам'яті безпосередньо одна за одною, доступ до яких здійснюється за індексом.
byte[] array = new byte[3];
Масиви використовуються для зберігання кількох значень в одній змінній замість оголошення окремих змінних для кожного значення.
Одновимірний масив – масив, який містить один індекс.
Способи створення одновимірних масивів
byte[] array = new byte[3];
byte array[] = new byte[3];
byte[] array = new byte[] { 1, 2, 3};
byte[] array = { 1, 2, 3};
Щоб оголосити масив, визначте тип змінної у квадратних дужках:
String[] cars;
Тепер ми оголосили змінну, яка містить масив рядків. Щоб вставити до нього значення, ми можемо використовувати литерал масиву – розмістити значення в списку, розділеному комами, у фігурних дужках:
String[] cars = {"Volvo", "", "", ""};
Щоб створити масив цілих чисел, ви можете написати:
int[] myNum = {10, 20, 30, 40};
Доступ до елементів масиву
Ви отримуєте доступ до елемента масиву, посилаючись на номер індексу.
Цей оператор отримує доступ до значення першого елемента в автомобілях:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
System.out.println(cars[0]); // Outputs Volvo
Змінити елемент масиву
Щоб змінити значення певного елемента, зверніться до номера індексу:
cars[0] = "Opel";
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
System.out.println(cars[0]);
// Now outputs Opel instead of Volvo
Array Length
Щоб дізнатися, скільки елементів має масив, скористайтеся властивістю length:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
System.out.println(cars.length); // Outputs ?
Цикл через масив
Ви можете перебирати елементи масиву за допомогою циклу for і використовувати властивість length, щоб вказати, скільки разів цикл має виконуватися.
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (int i = 0; i < cars.length; i++) {
System.out.println(cars[i]);
}
Цикл по масиву за допомогою For-Each
for (type variable : arrayname) {
...
}
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
System.out.println(i);
}
Багатовимірний масив — це масив масивів.
Багатовимірні масиви – масиви, що мають більше одного індексу:
Прямокутнi - Масиви, які містять кілька вимірів, де всі рядки мають однакову довжину.
byte[][] array = new byte[3][3];
byte[][] array = new byte[2][2];
array[0][0] = 10;
array[0][1] = 20;
array[1][0] = 30;
array[1][1] = 40;
Зубчасті - Масиви, які містять деяку кількість внутрішніх масивів, кожен з яких може мати власну унікальну верхню межу.
byte[][] array = new byte[3][];
array[0] = new byte[] {10, 20};
array[1] = new byte[] {30, 40, 50, 60};
array[2] = new byte[] {70, 80, 90};
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
myNumbers тепер є масивом із двома масивами як елементами.
Щоб отримати доступ до елементів масиву myNumbers, вкажіть два індекси: один для масиву, а другий для елемента всередині цього масиву. Цей приклад отримує доступ до третього елемента (2) у другому масиві (1) myNumbers:
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
int x = myNumbers[1][2];
System.out.println(x); // Outputs 7
Ми також можемо використовувати цикл for всередині іншого циклу for, щоб отримати елементи двовимірного масиву (нам все одно потрібно вказати на два індекси):
public class Main {
public static void main(String[] args) {
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
for (int i = 0; i < myNumbers.length; ++i) {
for(int j = 0; j < myNumbers[i].length; ++j) {
System.out.println(myNumbers[i][j]);
}
}
}
}
Тривимірні
byte[][][] array = new byte[3][3][3];
byte[][][] array = new byte[2][2][2];
array[0][0][0] = 10;
array[0][0][1] = 20;
array[0][1][0] = 30;
array[0][1][1] = 40;
array[1][0][0] = 50;
array[1][0][1] = 60;
array[1][1][0] = 70;
array[1][1][1] = 80;
Метод — це блок коду, який виконується лише тоді, коли його викликають.
Ви можете передати дані, відомі як параметри, у метод.
Методи використовуються для виконання певних дій, вони також відомі як функції.
Навіщо використовувати методи? Щоб повторно використовувати код: визначте код один раз і використовуйте його багато разів.
Метод повинен бути оголошений всередині класу. Він визначається назвою методу, за яким слідують дужки (). Java надає деякі попередньо визначені методи, такі як System.out.println(), але ви також можете створити власні методи для виконання певних дій:
public class Main {
static void myMethod() {
// code to be executed
}
}
Пояснений приклад
myMethod() — ім'я методу
static означає, що метод належить до класу Main, а не об'єкту класу Main. Ви дізнаєтеся більше про об’єкти та як отримати доступ до методів через об’єкти пізніше в цьому підручнику.
void означає, що цей метод не має повертати значення. Ви дізнаєтеся більше про повертаються значення пізніше в цьому розділі
public class Main {
static void myMethod() {
System.out.println("I am learning programming");
}
public static void main(String[] args) {
myMethod();
}
}
Метод також можна викликати кілька разів:
public class Main {
static void myMethod() {
System.out.println("I am learning programming");
}
public static void main(String[] args) {
myMethod();
myMethod();
myMethod();
}
}
Параметри та аргументи
Інформацію можна передати методам як параметр. Параметри діють як змінні всередині методу.
Параметри вказуються після імені методу в дужках. Ви можете додати скільки завгодно параметрів, просто відокремте їх комою.
У наступному прикладі є метод, який приймає в якості параметра рядок з назвою fname. Коли метод викликається, ми передаємо ім’я, яке використовується всередині методу для друку повного імені:
public class Main {
static void myMethod(String fname) {
System.out.println(fname + " Refsnes");
}
public static void main(String[] args) {
myMethod("Liam");
myMethod("Jenny");
myMethod("Anja");
}
}
Коли параметр передається методу, він називається аргументом. Отже, з прикладу вище: fname — це параметр, а Liam, Jenny та Jenny— аргументи.
Кілька параметрів
Ви можете мати скільки завгодно параметрів:
public class Main {
static void myMethod(String fname, int age) {
System.out.println(fname + " is " + age);
}
public static void main(String[] args) {
myMethod("Liam", 5);
myMethod("Jenny", 8);
myMethod("Anja", 31);
}
}
Зауважте, що коли ви працюєте з кількома параметрами, виклик методу повинен мати ту саму кількість аргументів, що й параметри, і аргументи повинні передаватися в тому самому порядку.
Повертаються значення
Ключове слово void, використане в наведених вище прикладах, вказує на те, що метод не повинен повертати значення. Якщо ви хочете, щоб метод повертав значення, ви можете використовувати примітивний тип даних (наприклад, int, char тощо) замість void і використовувати ключове слово return всередині методу:
public class Main {
static int myMethod(int x) {
return 5 + x;
}
public static void main(String[] args) {
System.out.println(myMethod(3));
}
}
Цей приклад повертає суму двох параметрів методу:
public class Main {
static int myMethod(int x, int y) {
return x + y;
}
public static void main(String[] args) {
System.out.println(myMethod(5, 3));
}
}
Ви також можете зберегти результат у змінній (рекомендовано, оскільки її легше читати та підтримувати):
public class Main {
static int myMethod(int x, int y) {
return x + y;
}
public static void main(String[] args) {
int z = myMethod(5, 3);
System.out.println(z);
}
}
Метод з If...Else
Зазвичай у методах використовуються оператори if...else:
public class Main {
static void checkAge(int age) {
if (age < 18) {
System.out.println("Access denied - You are not old enough!");
} else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(20);
}
}
При перевантаженні методів кілька методів можуть мати однакові назви з різними параметрами:
int myMethod(int x)
float myMethod(float x)
double myMethod(double x, double y)
Розглянемо наступний приклад, який містить два методи додавання чисел різного типу:
static int plusMethodInt(int x, int y) {
return x + y;
}
static double plusMethodDouble(double x, double y) {
return x + y;
}
public static void main(String[] args) {
int myNum1 = plusMethodInt(8, 5);
double myNum2 = plusMethodDouble(4.3, 6.26);
System.out.println("int: " + myNum1);
System.out.println("double: " + myNum2);
}
Замість визначення двох методів, які повинні робити те саме, краще перевантажити один.
У наведеному нижче прикладі ми перевантажуємо метод plusMethod для роботи як для int, так і для double:
static int plusMethod(int x, int y) {
return x + y;
}
static double plusMethod(double x, double y) {
return x + y;
}
public static void main(String[] args) {
int myNum1 = plusMethod(8, 5);
double myNum2 = plusMethod(4.3, 6.26);
System.out.println("int: " + myNum1);
System.out.println("double: " + myNum2);
}
Примітка. Кілька методів можуть мати однакові назви, якщо кількість і/або тип параметрів відрізняються.
Змінні, оголошені безпосередньо в методі, доступні в будь-якому місці методу після рядка коду, в якому вони були оголошені:
У Java змінні доступні лише в тій області, де вони створені. Це називається сферою застосування.
public class Main {
public static void main(String[] args) {
// Code here CANNOT use x
int x = 100;
// Code here can use x
System.out.println(x);
}
}
Область блоку
Блок коду стосується всього коду між фігурними дужками {}.
Змінні, оголошені всередині блоків коду, доступні лише за допомогою коду між фігурними дужками, який слідує за рядком, у якому було оголошено змінну:
public class Main {
public static void main(String[] args) {
// Code here CANNOT use x
{ // This is a block
// Code here CANNOT use x
int x = 100;
// Code here CAN use x
System.out.println(x);
} // The block ends here
// Code here CANNOT use x
}
}
Блок коду може існувати як сам по собі, так і належати оператору if, while або for. У випадку операторів for змінні, оголошені в самому операторі, також доступні в межах блоку.
Рекурсія — це техніка здійснення самого виклику функції. Ця техніка дає змогу розділити складні проблеми на прості, які легше вирішити.
Рекурсія може бути трохи складною для розуміння. Найкращий спосіб зрозуміти, як це працює, — поекспериментувати з ним.
Приклад рекурсії
Додавання двох чисел легко зробити, але додавання діапазону чисел складніше. У наступному прикладі рекурсія використовується для додавання діапазону чисел шляхом розбиття її на просте завдання додавання двох чисел:
public class Main {
public static void main(String[] args) {
int result = sum(10);
System.out.println(result);
}
public static int sum(int k) {
if (k > 0) {
return k + sum(k - 1);
} else {
return 0;
}
}
}
Коли викликається функція sum(), вона додає параметр k до суми всіх чисел, менших за k, і повертає результат. Коли k стає 0, функція просто повертає 0.
Стан зупинки
Подібно до того, як цикли можуть зіткнутися з проблемою нескінченного циклу, рекурсивні функції можуть зіткнутися з проблемою нескінченної рекурсії. Нескінченна рекурсія — це коли функція ніколи не припиняє викликати саму себе. Кожна рекурсивна функція повинна мати умову зупинки, яка є умовою, коли функція припиняє викликати саму себе. У попередньому прикладі умова зупинки – це коли параметр k стає 0.
Корисно побачити різноманітні приклади, щоб краще зрозуміти концепцію. У цьому прикладі функція додає діапазон чисел між початком і кінцем. Умова зупинки для цієї рекурсивної функції полягає в тому, що end не більше ніж start:
public class Main {
public static void main(String[] args) {
int result = sum(5, 10);
System.out.println(result);
}
public static int sum(int start, int end) {
if (end > start) {
return end + sum(start, end - 1);
} else {
return end;
}
}
}
Розробник має бути дуже обережним з рекурсією, оскільки може бути дуже легко скользнути до написання функції, яка ніколи не закінчується, або такої, яка використовує надмірну кількість пам’яті чи потужності процесора. Однак, коли рекурсія написана правильно, вона може бути дуже ефективним і математично елегантним підходом до програмування.
Git — розподілена система керування версіями файлів та спільної роботи. Проєкт створив Лінус Торвальдс для керування розробкою ядра Linux, а сьогодні підтримується Джуніо Хамано. Git є однією з найефективніших, надійних і високопродуктивних систем керування версіями, що надає гнучкі засоби нелінійної розробки, що базуються на відгалуженні та злитті гілок. Для забезпечення цілісності історії та стійкості до змін заднім числом використовуються криптографічні методи, також можлива прив'язка цифрових підписів розробників до тегів і комітів.
Прикладами проєктів, що використовують Git, є ядро Linux, Android, LibreOffice, Cairo, GNU Core Utilities, Mesa 3D, Wine, багато проєктів з X.org, XMMS2, GStreamer, Debian DragonFly BSD, Perl, Eclipse, GNOME, KDE, Qt, Ruby on Rails, PostgreSQL, VideoLAN, PHP, One Laptop Per Child (OLPC), АБІС Koha, GNU LilyPond та ELinks і деякі дистрибутиви GNU/Linux (див. нижче).
Програма є вільною і випущена під ліцензією GNU GPL версії 2.
Система спроєктована як набір програм, спеціально розроблених з врахуванням їхнього використання у скриптах. Це дозволяє зручно створювати спеціалізовані системи керування версіями на базі Git або користувацькі інтерфейси. Наприклад, Cogito є саме таким прикладом фронтенда до репозиторіїв Git. А StGit використовує Git для управління колекцією.
Система має ряд користувацьких інтерфейсів: наприклад, gitk та git-gui розповсюджуються з самим Git.
Віддалений доступ до репозиторіїв Git забезпечується git-демоном, SSH або HTTP сервером. TCP-сервіс git-daemon входить у дистрибутив Git і є разом з SSH найпоширенішим і надійним методом доступу. Метод доступу HTTP, хоч має низку обмежень, дуже популярний в контрольованих мережах, тому що дозволяє використання наявних конфігурацій мережевих фільтрів.
Git, на відміну від Subversion і подібних до неї систем, не зберігає інформацію як список змін (патчів) для файлів. Замість цього Git зберігає дані набором зліпків. Кожного разу при фіксації поточної версії проєкту Git зберігає зліпок того, як виглядають всі файли проєкту. Але якщо файл не змінювався, то дається посилання на раніше збережений файл (див. рис. 1). Git схожий на своєрідну файлову систему з інструментами, які працюють поверх неї. Для кожного відстежуваного файлу Git зберігає розмір, час створення та останньої зміни. Ці дані зберігаються у файлі index, який знаходиться у теці .git Вся база даних Git зберігається в теці з назвою .git
В Git файли можуть знаходитися в одному із 3-х станів: зафіксованому (файл вже збережено в локальній базі даних), зміненому (файл було змінено, але зміни не зафіксовано) і підготовленому (файли було змінено і відмічено для фіксації).
Більшість дій можна виконувати на локальній файловій системі без використання інтернет підключення. Вся історія змін зберігається локально і при необхідності вивантажується у віддалений репозиторій. На відміну від Subversion, де без підключення до інтернету можна лише редагувати файли, але зберегти зміни в вашу базу даних неможливо (оскільки вона відключена від репозиторію). Будь-який коміт спочатку робиться локально, а потім вивантажується у віддалений репозиторій.
У своїй базі Git зберігає все по хешам файлів, які хешуються функцією SHA-1. Перед кожним збереженням файлів Git обчислює SHA-1 хеш файлу й отриманий хеш стає індексом файлу в Git. Використовуючи хеш Git легко відстежує зміни в файлах.
Галуження — це розмежування від основної лінії розробки. Git дозволяє створити декілька гілок і перемикатися між ними. Це корисно, оскільки дозволяє працювати декільком розробникам над своїм функціоналом не заважаючи іншим і не псуючи основну гілку. За замовчуванням, Git створює гілку з назвою master. Гілка в Git просто являє собою вказівник на одну із фіксацій. При кожній новій фіксації гілка в Git рухається автоматично (тобто перемикається на фіксацію). Гілка є простим файлом, який містить 40 символів контрольної суми SHA-1 фіксації. Створення нової гілки дуже швидке, оскільки це однаково запису в файл 41 байта (40 символів + символ нового рядка).
Git підтримує два способи для інтеграції змін з гілки в гілку: merge (зливання) та rebase (перебазування). Основна різниця полягає в тому, що rebase запам'ятовує фіксації у вигляді патчів, перемотує гілку і застосовує патчі у вигляді фіксацій на відміну від merge, який зливає дві гілки в одну.
Додаємо всі файли
$ cd <path_project> #Шлях до проєкту (наприклад: $ cd с:/www/git). Переходимо в наявну теку, в якій буде розміщено проєкт
$ git init #Ініціалізація репозиторію. Створює в каталозі Project каталог .git і в ньому всі необхідні файли репозиторію
$ git add . #Додаємо всі файли, які наявні в каталозі Project, під версійний контроль
$ git commit -m "Коментар" #Фіксуємо зміни
$ git clone <remote_path_project> #Проєкт буде клоновано з віддаленого сервера у поточний локальний каталог (наприклад, https://github.com/git/git.git)
$ git pull #Всі файли будуть оновлені до останньої версії з віддаленого сервера
$ git log #Відображає всі зміни, зроблені в поточній гілці проєкту в хронологічному порядку
Видалення з індексу
$ git rm --cached README.txt #Видалення файлу README.txt з індексу, тобто він фізично залишається, але зміни в ньому не відстежуються.
Видалення з репозиторію
$ git rm README.txt #Видалення файлу README.txt з робочого каталогу та індексу !!! Використовувати уважно!
Рекурсивне видалення
$ git rm --cached -r . #Видалення з індексу всіх файлів в поточному каталозі, включаючи вкладені каталоги
Створення нової гілки
$ git branch new_branch # Створення нової гілки з назвою new_branch
$ git checkout new_branch # Перемикання на гілку new_branch
Перегляд всіх гілок
$ git branch # Переглянути всі гілки
Java OOP
ООП
Класи та об’єкти Java
Атрибуты Классу
Модифiкатори
ООП означає об'єктно-орієнтоване програмування.
Процедурне програмування — це написання процедур або методів, які виконують операції над даними, тоді як об’єктно-орієнтоване програмування — це створення об’єктів, які містять як дані, так і методи.
Об'єктно-орієнтоване програмування має кілька переваг перед процедурним:
ООП швидший і легший у виконанні
ООП забезпечує чітку структуру для програм
ООП допомагає зберегти код Java СУХИМ "Не повторюйтесь" і полегшує підтримку, зміну та налагодження коду
ООП дає змогу створювати повністю багаторазові програми з меншим кодом і коротшим часом розробки
Порада. Принцип «Не повторюйся» (DRY) спрямований на зменшення повторення коду. Ви повинні вилучити коди, які є загальними для програми, розмістити їх в одному місці та повторно використовувати замість повторення.
Java - Що таке класи та об'єкти?
Класи та об'єкти є двома основними аспектами об'єктно-орієнтованого програмування.
Отже, клас — це шаблон для об’єктів, а об’єкт — це екземпляр класу.
Коли окремі об’єкти створюються, вони успадковують усі змінні та методи класу.
Усе в Java пов’язане з класами та об’єктами разом із його атрибутами та методами. Наприклад: у реальному житті автомобіль є предметом. Автомобіль має атрибути, такі як вага та колір, і методи, такі як водіння та гальмування.
Клас схожий на конструктор об’єктів або «схему» для створення об’єктів.
Створіть клас
Щоб створити клас, використовуйте ключове слово class:
public class Main {
int x = 5;
}
Пам’ятайте «Синтаксис Java», що клас завжди має починатися з великої першої літери, і що ім’я файлу Java має відповідати імені класу.
Створіть об'єкт
У Java об’єкт створюється з класу. Ми вже створили клас під назвою Main, тож тепер ми можемо використовувати його для створення об’єктів.
Щоб створити об’єкт Main, вкажіть ім’я класу, потім ім’я об’єкта та використовуйте ключове слово new:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
Кілька об'єктів
Ви можете створити кілька об'єктів одного класу:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj1 = new Main(); // Object 1
Main myObj2 = new Main(); // Object 2
System.out.println(myObj1.x);
System.out.println(myObj2.x);
}
}
Використання кількох класів
Ви також можете створити об’єкт класу та отримати доступ до нього в іншому класі. Це часто використовується для кращої організації класів (один клас має всі атрибути та методи, а інший клас містить метод main() (код для виконання)).
Пам’ятайте, що ім’я java-файлу має відповідати імені класу. У цьому прикладі ми створили два файли в одному каталозі/папці:
Main.java
Second.java
public class Main {
int x = 5;
}
class Second {
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
У попередньому розділі ми використовували термін «змінна» для x у прикладі (як показано нижче). Насправді це атрибут класу. Або ви можете сказати, що атрибути класу є змінними всередині класу:
public class Main {
int x = 5;
int y = 3;
}
Іншим терміном для атрибутів класу є поля.
Доступ до атрибутів
Ви можете отримати доступ до атрибутів, створивши об’єкт класу та використовуючи синтаксис крапки (.):
У наступному прикладі буде створено об’єкт класу Main з назвою myObj. Ми використовуємо атрибут x на об’єкті, щоб надрукувати його значення:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
Змінити атрибути
Ви також можете змінювати значення атрибутів:
public class Main {
int x;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 40;
System.out.println(myObj.x);
}
}
Або перевизначте існуючі значення:
public class Main {
int x = 10;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 25; // x is now 25
System.out.println(myObj.x);
}
}
Якщо ви не хочете мати можливість перевизначати існуючі значення, оголосите атрибут як final:
public class Main {
final int x = 10;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 25; // will generate an error: cannot assign a value to a final variable
System.out.println(myObj.x);
}
}
Ключове слово final корисне, коли ви хочете, щоб змінна завжди зберігала те саме значення, наприклад PI (3,14159...).
Остаточне ключове слово називається «модифікатор». Ви дізнаєтеся більше про них у розділі «Модифікатори Java».
Кілька об'єктів
Якщо ви створюєте кілька об’єктів одного класу, ви можете змінити значення атрибутів в одному об’єкті, не впливаючи на значення атрибутів в іншому:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj1 = new Main(); // Object 1
Main myObj2 = new Main(); // Object 2
myObj2.x = 25;
System.out.println(myObj1.x); // Outputs 5
System.out.println(myObj2.x); // Outputs 25
}
}
Кілька атрибутів
Ви можете вказати скільки завгодно атрибутів:
public class Main {
String fname = "John";
String lname = "Doe";
int age = 24;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println("Name: " + myObj.fname + " " + myObj.lname);
System.out.println("Age: " + myObj.age);
}
}
З розділу «Методи Java» ви дізналися, що методи оголошуються в класі та використовуються для виконання певних дій:
public class Main {
static void myMethod() {
System.out.println("Hello World!");
}
public static void main(String[] args) {
myMethod();
}
}
Статичний проти публічного
Ви часто бачите програми Java, які мають статичні або публічні атрибути та методи.
У наведеному вище прикладі ми створили static метод, що означає, що до нього можна отримати доступ без створення об’єкта класу, на відміну від public, до якого можна отримати доступ лише за допомогою об’єктів:
public class Main {
// Static method
static void myStaticMethod() {
System.out.println("Static methods can be called without creating objects");
}
// Public method
public void myPublicMethod() {
System.out.println("Public methods must be called by creating objects");
}
public static void main(String[] args) {
myStaticMethod(); // Call the static method
// myPublicMethod(); This would compile an error
Main myObj = new Main(); // Create an object of Main
myObj.myPublicMethod(); // Call the public method on the object
}
}
Методи доступу з об’єктом
public class Main {
// Create a fullThrottle() method
public void fullThrottle() {
System.out.println("The car is going as fast as it can!");
}
// Create a speed() method and add a parameter
public void speed(int maxSpeed) {
System.out.println("Max speed is: " + maxSpeed);
}
// Inside main, call the methods on the myCar object
public static void main(String[] args) {
Main myCar = new Main(); // Create a myCar object
myCar.fullThrottle(); // Call the fullThrottle() method
myCar.speed(200); // Call the speed() method
}
}
Пояснення прикладу
1) Ми створили спеціальний клас Main з ключовим словом class.
2) Ми створили методи fullThrottle() і speed() у класі Main.
3) Методи fullThrottle() і speed() виведуть текст під час їх виклику.
4) Метод speed() приймає параметр int під назвою maxSpeed - ми будемо використовувати його в 8).
5) Щоб використовувати клас Main та його методи, нам потрібно створити об’єкт Main Class.
6) Потім перейдіть до методу main(), який, як ви вже знаєте, є вбудованим методом Java, який запускає вашу програму (виконується будь-який код усередині main).
7) Використовуючи ключове слово new, ми створили об’єкт із назвою myCar.
8) Потім ми викликаємо методи fullThrottle() і speed() для об’єкта myCar і запускаємо програму, використовуючи ім’я об’єкта (myCar), за яким стоїть крапка (.), а потім ім’я методу (fullThrottle(); і speed(200);). Зверніть увагу, що ми додаємо параметр int 200 у метод speed().
Пам'ятайте, що:
Крапка (.) використовується для доступу до атрибутів і методів об’єкта.
Щоб викликати метод у Java, напишіть ім’я методу, за яким стоять дужки (), а потім крапка з комою (;).
Клас повинен мати відповідну назву файлу (Main і Main.java).
Використання кількох класів
Як ми зазначали в розділі «Класи», гарною практикою є створення об’єкта класу та доступ до нього в іншому класі.
Пам’ятайте, що ім’я java-файлу має відповідати імені класу. У цьому прикладі ми створили два файли в одному каталозі:
Main.java
Second.java
public class Main {
public void fullThrottle() {
System.out.println("The car is going as fast as it can!");
}
public void speed(int maxSpeed) {
System.out.println("Max speed is: " + maxSpeed);
}
}
----------------------------------------------------------------
class Second {
public static void main(String[] args) {
Main myCar = new Main(); // Create a myCar object
myCar.fullThrottle(); // Call the fullThrottle() method
myCar.speed(200); // Call the speed() method
}
}
Конструктор в Java - це спеціальний метод, який використовується для ініціалізації об'єктів. Конструктор викликається, коли створюється об'єкт класу. Його можна використовувати для встановлення початкових значень для атрибутів об’єкта:
public class Main {
int x; // Create a class attribute
// Create a class constructor for the Main class
public Main() {
x = 5; // Set the initial value for the class attribute x
}
public static void main(String[] args) {
Main myObj = new Main(); // Create an object of class Main (This will call the constructor)
System.out.println(myObj.x); // Print the value of x
}
}
Зауважте, що ім’я конструктора має відповідати імені класу, і воно не може мати тип повернення (наприклад, void).
Також зауважте, що конструктор викликається під час створення об’єкта.
Усі класи мають конструктори за замовчуванням: якщо ви не створюєте конструктор класу самостійно, Java створює його для вас. Однак тоді ви не зможете встановити початкові значення для атрибутів об’єкта.
Параметри конструктора
Конструктори також можуть приймати параметри, які використовуються для ініціалізації атрибутів.
У наступному прикладі до конструктора додається параметр int y. Усередині конструктора ми встановлюємо x рівним y (x=y). Коли ми викликаємо конструктор, ми передаємо параметр конструктору (5), який встановить значення x рівним 5:
public class Main {
int x;
public Main(int y) {
x = y;
}
public static void main(String[] args) {
Main myObj = new Main(5);
System.out.println(myObj.x);
}
}
Ви можете мати скільки завгодно параметрів:
public class Main {
int modelYear;
String modelName;
public Main(int year, String name) {
modelYear = year;
modelName = name;
}
public static void main(String[] args) {
Main myCar = new Main(1969, "Mustang");
System.out.println(myCar.modelYear + " " + myCar.modelName);
}
}
Наразі ви добре знайомі з ключовим словом public, яке зустрічається майже в усіх прикладах:
public class Main
Ключове слово public є модифікатором доступу, що означає, що воно використовується для встановлення рівня доступу для класів, атрибутів, методів і конструкторів.
Ми поділяємо модифікатори на дві групи:
Access Modifiers - контролює рівень доступу
Non-Access Modifiers - не контролюють рівень доступу, але надають інші функції
Модифікатори доступу
Для класів ви можете використовувати public або default:
public - Клас доступний для будь-якого іншого класу
default (за замовчуванням) - Клас доступний лише для класів у тому самому пакеті. Це використовується, коли ви не вказуєте модифікатор. Ви дізнаєтеся більше про пакети в розділі «Пакунки».
Для атрибутів, методів і конструкторів ви можете використовувати одне з наступного:
public Код доступний для всіх класів
private Код доступний лише в межах оголошеного класу
default (за замовчуванням) - Код доступний лише в одному пакеті. Це використовується, коли ви не вказуєте модифікатор. Ви дізнаєтеся більше про пакети в розділі «Пакунки».
protected Код доступний у тому самому пакеті та підкласах. Ви дізнаєтесь більше про підкласи та суперкласи в розділі «Наслідування».
Модифікатори без доступу
Для класів ви можете використовувати final або abstract:
final Клас не може бути успадкований іншими класами (Ви дізнаєтеся більше про успадкування в розділі Спадкування)
abstract Клас не можна використовувати для створення об’єктів (щоб отримати доступ до абстрактного класу, його потрібно успадкувати від іншого класу. Ви дізнаєтесь більше про успадкування та абстракцію в розділах «Наслідування» та «Абстракція»)
Для атрибутів і методів можна використовувати один із таких:
final - Атрибути та методи не можна перевизначати/змінювати
static - Атрибути та методи належать класу, а не об'єкту
abstract - Може використовуватися лише в абстрактному класі та лише в методах. Метод не має тіла, наприклад abstract void run();. Тіло надається підкласом (успадковується від). Ви дізнаєтесь більше про успадкування та абстракцію в розділах про успадкування та абстракцію
transient - Атрибути та методи пропускаються під час серіалізації об’єкта, що їх містить
synchronized - методи можуть бути доступні лише одному потоку одночасно
volatile - Значення атрибута не кешується локально потоком, а завжди читається з "основної пам'яті"
Якщо ви не хочете мати можливість замінювати існуючі значення атрибутів, оголосите атрибути як final:
public class Main {
final int x = 10;
final double PI = 3.14;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 50; // will generate an error: cannot assign a value to a final variable
myObj.PI = 25; // will generate an error: cannot assign a value to a final variable
System.out.println(myObj.x);
}
}
static метод означає, що до нього можна отримати доступ без створення об’єкта класу, на відміну від public:
public class Main {
// Static method
static void myStaticMethod() {
System.out.println("Static methods can be called without creating objects");
}
// Public method
public void myPublicMethod() {
System.out.println("Public methods must be called by creating objects");
}
// Main method
public static void main(String[ ] args) {
myStaticMethod(); // Call the static method
// myPublicMethod(); This would output an error
Main myObj = new Main(); // Create an object of Main
myObj.myPublicMethod(); // Call the public method
}
}
abstract метод належить до abstract класу і не має тіла. Тіло представлено підкласом:
abstract class Main {
public String fname = "John";
public int age = 24;
public abstract void study(); // abstract method
}
// Subclass (inherit from Main)
class Student extends Main {
public int graduationYear = 2018;
public void study() { // the body of the abstract method is provided here
System.out.println("Studying all day long");
}
}
// End code from filename: Main.java
// Code from filename: Second.java
class Second {
public static void main(String[] args) {
// create an object of the Student class (which inherits attributes and methods from Main)
Student myObj = new Student();
System.out.println("Name: " + myObj.fname);
System.out.println("Age: " + myObj.age);
System.out.println("Graduation Year: " + myObj.graduationYear);
myObj.study(); // call abstract method
}
}
Сенс інкапсуляції полягає в тому, щоб переконатися, що "конфіденційні" дані приховані від користувачів. Щоб досягти цього, ви повинні:
оголошувати змінні/атрибути класу як private
надати загальнодоступні методи get і set для доступу та оновлення значення приватної змінної
Отримати та встановити
З попереднього розділу ви дізналися, що приватні змінні можуть бути доступні лише в межах одного класу (зовнішній клас не має до них доступу). Однак доступ до них можливий, якщо ми надамо публічні методи get і set.
Метод get повертає значення змінної, а метод set встановлює значення.
Синтаксис для обох полягає в тому, що вони починаються з get або set, після чого йде ім’я змінної з першою літерою у верхньому регістрі:
public class Person {
private String name; // private = restricted access
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String newName) {
this.name = newName;
}
}
Метод get повертає значення імені змінної.
Метод set приймає параметр (newName) і призначає його змінній name. Ключове слово this використовується для посилання на поточний об’єкт.
Чому саме інкапсуляція?
Кращий контроль атрибутів і методів класу
Атрибути класу можна зробити лише для читання (якщо ви використовуєте лише метод get) або лише для запису (якщо ви використовуєте лише метод set)
Гнучкий: програміст може змінити одну частину коду, не впливаючи на інші частини
Підвищена безпека даних
Пакет у Java використовується для групування пов’язаних класів. Уявіть це як папку в каталозі файлів. Ми використовуємо пакети, щоб уникнути конфліктів імен і написати код, який краще підтримувати. Пакети діляться на дві категорії:
Вбудовані пакети (пакети з Java API)
Визначені користувачем пакети (створіть власні пакети)
Вбудовані пакети
Java API — це бібліотека попередньо написаних класів, якими можна користуватися безкоштовно, які включені в середовище розробки Java.
Бібліотека містить компоненти для керування введенням, програмування баз даних та багато іншого. Повний список можна знайти на веб-сайті Oracles: https://docs.oracle.com/javase/8/docs/api/.
Бібліотека розділена на пакети та класи. Це означає, що ви можете імпортувати один клас (разом із його методами й атрибутами) або цілий пакет, який містить усі класи, що належать до зазначеного пакету.
Щоб використовувати клас або пакет із бібліотеки, вам потрібно використати ключове слово import:
import package.name.Class; // Import a single class
import package.name.*; // Import the whole package
Імпортувати клас
Якщо ви знайшли клас, який хочете використовувати, наприклад, клас Scanner, який використовується для отримання введених даних користувачами, напишіть наступний код:
import java.util.Scanner;
У наведеному вище прикладі java.util є пакетом, тоді як Scanner є класом пакета java.util.
Щоб використовувати клас Scanner, створіть об’єкт класу та скористайтеся будь-яким із доступних методів, знайдених у документації класу Scanner. У нашому прикладі ми будемо використовувати метод nextLine(), який використовується для читання повного рядка:
import java.util.Scanner;
class MyClass {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in);
System.out.println("Enter username");
String userName = myObj.nextLine();
System.out.println("Username is: " + userName);
}
}
Імпортувати пакет
Є багато пакетів на вибір. У попередньому прикладі ми використовували клас Scanner з пакету java.util. Цей пакет також містить засоби дати та часу, генератор випадкових чисел та інші корисні класи.
Щоб імпортувати цілий пакет, закінчіть речення знаком зірочки (*). У наступному прикладі буде імпортовано ВСІ класи в пакеті java.util:
import java.util.*;
Визначені користувачем пакети
Щоб створити власний пакет, вам потрібно розуміти, що Java використовує каталог файлової системи для їх зберігання. Так само, як папки на вашому комп’ютері:
└── root
└── mypack
└── MyPackageClass.java
Щоб створити пакет, використовуйте ключове слово пакета:
package mypack;
class MyPackageClass {
public static void main(String[] args) {
System.out.println("This is my package!");
}
}
Спадкування Java (підклас і суперклас)
У Java є можливість успадковувати атрибути та методи від одного класу до іншого. Ми групуємо «концепцію успадкування» у дві категорії:
підклас (дочірній) - клас, який успадковує інший клас
суперклас (батьківський) - клас, який успадковується
Щоб успадкувати від класу, використовуйте ключове слово extends.
У наведеному нижче прикладі клас (підклас) Car успадковує атрибути та методи від класу Vehicle (суперклас):
class Vehicle {
protected String brand = "Ford"; // Vehicle attribute
public void honk() { // Vehicle method
System.out.println("Tuut, tuut!");
}
}
class Car extends Vehicle {
private String modelName = "Mustang"; // Car attribute
public static void main(String[] args) {
// Create a myCar object
Car myCar = new Car();
// Call the honk() method (from the Vehicle class) on the myCar object
myCar.honk();
// Display the value of the brand attribute (from the Vehicle class) and the value of the modelName from the Car class
System.out.println(myCar.brand + " " + myCar.modelName);
}
}
Ви помітили модифікатор protected у Vehicle?
Ми встановлюємо атрибут brand у Vehicle на модифікатор protected доступу. Якщо його було встановлено як private, клас автомобіля не мав би доступу до нього.
Навіщо і коли використовувати «Наслідування»?
- Це корисно для повторного використання коду: повторно використовуйте атрибути та методи існуючого класу під час створення нового класу.
Порада: також перегляньте наступний розділ «Поліморфізм», у якому використовуються успадковані методи для виконання різних завдань.
Ключове слово final
Якщо ви не хочете, щоб інші класи успадковували клас, використовуйте ключове слово final:
Поліморфізм означає «багато форм», і це відбувається, коли ми маємо багато класів, пов’язаних один з одним успадкуванням.
Як ми вказали в попередньому розділі; Спадкування дозволяє нам успадковувати атрибути та методи з іншого класу. Поліморфізм використовує ці методи для виконання різних завдань. Це дозволяє нам виконувати одну дію різними способами.
Наприклад, подумайте про суперклас під назвою Animal, який має метод під назвою animalSound(). Підкласами тварин можуть бути свині, коти, собаки, птахи, і вони також мають власну реалізацію звуку тварин (свиня хрює, а кіт нявкає тощо):
class Animal {
public void animalSound() {
System.out.println("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
System.out.println("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
System.out.println("The dog says: bow wow");
}
}
Пам’ятайте з глави «Наслідування», що ми використовуємо ключове слово extends для успадкування від класу.
Тепер ми можемо створити об’єкти Pig і Dog і викликати метод animalSound() для обох з них:
class Animal {
public void animalSound() {
System.out.println("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
System.out.println("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
System.out.println("The dog says: bow wow");
}
}
class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
myAnimal.animalSound();
myPig.animalSound();
myDog.animalSound();
}
}
Чому і коли використовувати «успадкування» та «поліморфізм»?
- Це корисно для повторного використання коду: повторно використовуйте атрибути та методи існуючого класу під час створення нового класу.
У Java також можливо вкладати класи (клас у класі). Метою вкладених класів є групування класів, які належать один одному, що робить ваш код більш читабельним і зручним для обслуговування.
Щоб отримати доступ до внутрішнього класу, створіть об’єкт зовнішнього класу, а потім створіть об’єкт внутрішнього класу:
class OuterClass {
int x = 10;
class InnerClass {
int y = 5;
}
}
public class Main {
public static void main(String[] args) {
OuterClass myOuter = new OuterClass();
OuterClass.InnerClass myInner = myOuter.new InnerClass();
System.out.println(myInner.y + myOuter.x);
}
}
Приватний внутрішній клас
На відміну від «звичайного» класу, внутрішній клас може бути закритим або захищеним. Якщо ви не хочете, щоб зовнішні об’єкти отримували доступ до внутрішнього класу, оголосите клас приватним:
Якщо ви намагаєтесь отримати доступ до приватного внутрішнього класу із зовнішнього класу, виникає помилка:
Статичний внутрішній клас
Внутрішній клас також може бути статичним, що означає, що ви можете отримати доступ до нього без створення об’єкта зовнішнього класу:
class OuterClass {
int x = 10;
static class InnerClass {
int y = 5;
}
}
public class Main {
public static void main(String[] args) {
OuterClass.InnerClass myInner = new OuterClass.InnerClass();
System.out.println(myInner.y);
}
}
Примітка: як і статичні атрибути та методи, статичний внутрішній клас не має доступу до членів зовнішнього класу.
Доступ до зовнішнього класу з внутрішнього класу
Однією з переваг внутрішніх класів є те, що вони можуть отримати доступ до атрибутів і методів зовнішнього класу:
class OuterClass {
int x = 10;
class InnerClass {
public int myInnerMethod() {
return x;
}
}
}
public class Main {
public static void main(String[] args) {
OuterClass myOuter = new OuterClass();
OuterClass.InnerClass myInner = myOuter.new InnerClass();
System.out.println(myInner.myInnerMethod());
}
}
Абстракція даних — це процес приховування певних деталей і показу користувачеві лише важливої інформації.
Абстракції можна досягти або за допомогою абстрактних класів, або інтерфейсів (про які ви дізнаєтеся більше в наступному розділі).
Ключове слово abstract є модифікатором без доступу, який використовується для класів і методів:
Абстрактний клас: обмежений клас, який не можна використовувати для створення об’єктів (щоб отримати до нього доступ, його потрібно успадкувати від іншого класу).
Абстрактний метод: може використовуватися лише в абстрактному класі, і він не має тіла. Тіло надається підкласом (успадковується від).
Абстрактний клас може мати як абстрактні, так і звичайні методи:
abstract class Animal {
public abstract void animalSound();
public void sleep() {
System.out.println("I'm sleep");
}
З наведеного вище прикладу неможливо створити об’єкт класу Animal:
Animal myObj = new Animal(); // will generate an error
Щоб отримати доступ до абстрактного класу, його потрібно успадкувати від іншого класу. Давайте перетворимо клас Animal, який ми використовували в розділі про поліморфізм, на абстрактний клас:
Пам’ятайте з глави «Наслідування», що ми використовуємо ключове слово extends для успадкування від класу.
// Abstract class
abstract class Animal {
// Abstract method (does not have a body)
public abstract void animalSound();
// Regular method
public void sleep() {
System.out.println("I'm sleep");
}
}
// Subclass (inherit from Animal)
class Pig extends Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
}
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
Навіщо і коли використовувати абстрактні класи та методи?
Щоб забезпечити безпеку, приховайте певні деталі та показуйте лише важливі деталі об’єкта.
Примітка. Абстракції також можна досягти за допомогою інтерфейсів, про які ви дізнаєтеся більше в наступному розділі.
Ще один спосіб досягнення абстракції в Java – це інтерфейси.
Інтерфейс — це повністю «абстрактний клас», який використовується для групування пов’язаних методів із порожніми тілами:
// interface
interface Animal {
public void animalSound(); // interface method (does not have a body)
public void run(); // interface method (does not have a body)
}
Щоб отримати доступ до методів інтерфейсу, інтерфейс має бути «реалізований» (начебто успадкований) іншим класом із ключовим словом implements (замість extends). Тіло методу інтерфейсу надається класом "implement":
// Interface
interface Animal {
public void animalSound(); // interface method (does not have a body)
public void sleep(); // interface method (does not have a body)
}
// Pig "implements" the Animal interface
class Pig implements Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
public void sleep() {
// The body of sleep() is provided here
System.out.println("I'm sleep");
}
}
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
Примітки щодо інтерфейсів:
Як і абстрактні класи, інтерфейси не можна використовувати для створення об’єктів (у наведеному вище прикладі неможливо створити об’єкт «Animal» у MyMainClass)
Методи інтерфейсу не мають тіла - тіло надається класом "implement".
Під час реалізації інтерфейсу ви повинні перевизначити всі його методи
Методи інтерфейсу за замовчуванням абстрактні та публічні
Атрибути інтерфейсу за замовчуванням публічні, статичні та остаточні
Інтерфейс не може містити конструктор (оскільки його не можна використовувати для створення об’єктів)
Чому і коли використовувати інтерфейси?
1) Щоб досягти безпеки - приховайте певні деталі та показуйте лише важливі деталі об'єкта (інтерфейсу).
2) Java не підтримує «множинне успадкування» (клас може успадковувати лише один суперклас). Однак цього можна досягти за допомогою інтерфейсів, оскільки клас може реалізувати декілька інтерфейсів. Примітка. Щоб реалізувати кілька інтерфейсів, розділяйте їх комою (див. приклад нижче).
Кілька інтерфейсів
Щоб реалізувати кілька інтерфейсів, розділіть їх комою:
interface FirstInterface {
public void myMethod(); // interface method
}
interface SecondInterface {
public void myOtherMethod(); // interface method
}
class DemoClass implements FirstInterface, SecondInterface {
public void myMethod() {
System.out.println("Some text..");
}
public void myOtherMethod() {
System.out.println("Some other text...");
}
}
class Main {
public static void main(String[] args) {
DemoClass myObj = new DemoClass();
myObj.myMethod();
myObj.myOtherMethod();
}
}
Анонімний клас (anonymous class) – вкладений клас без імені. Анонімні класи використовуються за необхідності нової абстракції, з якою зручно працювати в межах методу, і вона не потрібна за його межами.
Анонімний клас Анонімні класи Якщо є необхідність створити на базі класу А новий клас і створити екземпляр класу В безпосередньо в цьому місці коду і більше цей об'єкт використовуватися не буде. Можна реалізувати це звичайним успадкуванням:
class B extends A {
... опис полів і методів породженого класу...
}
…
A b = new B();
або використати анонімний клас:
A a = new A() {
...
опис полів і методів породженого класу...
};
Приклад використання
На підставі анонімного класу створюється потік і запускається за допомогою методу start класу Thread. Синтаксис створення анонімного класу ґрутнується на використанні оператора new з ім'ям класу (інтерфейсу) і тілом нового анонімного класу.
new Thread(new Runnable() {
public void run(){
...
}
}).start();
Обмеження анонімних класів
Основне обмеження під час використання анонімних класів – це неможливість опису конструктора, оскільки клас немає імені. Аргументи, які вказані у дужках, автоматично використовуються для виклику конструктора базового класу з тими самими параметрами.
class A {
A(int param) {
}
public static void main(String[] args) {
new A(1) {}; // правильне створення анонімного класу
new A() { }; // неправильне створення анонімного класу
}
}
Обмеження анонімних класів
Обмеження в анонімних класів такі ж як і в локальних класів:
• їх видно лише в межах блоку, в якому оголошені;
• вони не можуть бути оголошені як private, public, protected чи static;
• вони не можуть мати у собі статичних оголошень (полів, методів, класів), винятком є константи (static final).
Переваги анонімних класів
Використання анонімних класів виправдане у багатьох випадках, зокрема коли: • тіло класу є дуже коротким; • потрібен лише один екземпляр класу; • клас використовується у місці його створення або відразу після нього; • ім'я класу не є важливим і не полегшує розуміння код
Масив – тип чи структура даних у вигляді набору компонентів (елементів масиву), які розміщені у пам'яті безпосередньо один за одним. Водночас доступ до окремих елементів масиву здійснюється за допомогою індексації, тобто посилання на масив із зазначенням номера (індексу) потрібного елемента. Завдяки цьому, на відміну від списку, масив є структурою з довільним доступом. Розмірність масиву – це кількість індексів, яка необхідна для однозначного доступу до елемента масиву.
Форма масиву – кількість розмірностей плюс розмір (протяжність) масиву для кожної розмірності. У Java масиви є об'єктами.
Оголошення масиву
Одночасне оголошення змінної та визначення масиву:
int[] array = new int[10];
Якщо масив створюється у такий спосіб, то всім елементам масиву автоматично надаються значення за замовчуванням. Наприклад, для числових значень початкове значення буде 0. Для масиву типу boolean початкове значення буде дорівнює false, для масиву типу char – '\u0000' , для масиву типу класу (об'єкти) – null.
Щоб проініціалізувати масив власними значеннями, просто перерахуйте їх:
int[] array = {2, 5, 7, 8, 3, 0};
Масиви мають фіксований розмір. Після створення масив не може зменшуватись або збільшуватися.
Методи роботи з масивами
Для роботи з масивами використовується клас java.util.Arrays
• Arrays.fill(int[] array, int value) дублює задане значення в кожному елементі масиву.
• Arrays.sort(Object[] array) проводить сортування масиву за зростанням.
• Arrays.toString(Object[] array) повертає рядок з елементами масиву. Якщо масив містить об'єкти, то повертає адресу об'єкта (для масивів у вигляді I@77vedf86).
• Arrays.deepToString(Object[] array) повертає рядок з елементами масиву. Якщо масив містить об'єкти, то повертає значення об'єкта (для масивів [0, 1, 2, 3]).
• Arrays.equals(Object[] array1, Object[] array2) порівнює два масиви. Умови рівності: масиви мають містити однакову кількість елементів, кожен елемент має бути еквівалентним відповідному елементу іншого масиву.
Копіювання масивів
System.arraycopy() – спеціальний метод копіювання масивів. Копіює в наявний масив.
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
• src – вихідний масив;
• srcPos – з якої позиції вихідного масиву розпочати копіювання;
• dest – масив, в який копіювати;
• destPos – з якої позиції розпочати вставлення елементів;
• length – кількість елементів, що копіюються.
Arrays.copyOf() – метод класу Arrays для копіювання масивів. Повертає новий масив.
Arrays.copyOf(T[] original, int newLength)
• original – вихідний масив;
• newLength – розмір нового масиву, що повертається.
Список ArrayList
ArrayList – масив, що автоматично розширюється, може змінювати свій розмір в процесі виконання програми.
ArrayList list = new ArrayList();
Елементи ArrayList можуть бути будь-якого типу, але в одному списку можуть бути елементи тільки одного типу. Щоб явно вказати, якого типу елементи зберігатимуться у списку, під час створення списку необхідно явно вказати тип елементів, які зберігатимуться в ньому:
ArrayList list = new ArrayList();
Такий запис каже, що ми використовували дженерик (узагальнення) з типізованими параметрами. У Java 7 з'явився вкорочений (ромбоподібний) запис:
Методи класу ArrayList
add(E element) вставляє елемент element наприкінці списку.
add(int index, E element) вставляє елемент element на позицію index.
remove(int index) видаляє елемент за певною позицією index.
remove(Object o) видаляє перший знайдений елемент, якщо він наявний у списку.
clear() видаляє усі елементи списку.
get(int index) повертає елемент, який розташований на позиції index.
set(int index, E element) заміщує елемент на позиції index елементом element.
size() повертає кількість елементів у списку.
toArray() повертає масив, який містить усі елементи списку.
indexOf(Object o) повертає позицію елемента o у списку або -1, якщо елемента немає. contains(Object o) повертає true, якщо список містить елемент o.
Enum — це спеціальний «клас», який представляє групу констант (незмінних змінних, як кінцеві змінні).
Щоб створити перелік, використовуйте ключове слово enum (замість класу чи інтерфейсу) і розділяйте константи комами. Зверніть увагу, що вони повинні бути написані великими літерами:
enum Level {
LOW,
MEDIUM,
HIGH
}
Ви можете отримати доступ до констант enum за допомогою крапкового синтаксису:
Level myVar = Level.MEDIUM;
Enum є скороченням від "enumerations", що означає "конкретно перерахований".
Enum всередині класу
Ви також можете мати enum всередині класу:
public class Main {
enum Level {
LOW,
MEDIUM,
HIGH
}
public static void main(String[] args) {
Level myVar = Level.MEDIUM;
System.out.println(myVar);
}
}
Enum у операторі Switch
Enum часто використовуються в операторах switch для перевірки відповідних значень:
enum Level {
LOW,
MEDIUM,
HIGH
}
public class Main {
public static void main(String[] args) {
Level myVar = Level.MEDIUM;
switch(myVar) {
case LOW:
System.out.println("Low level");
break;
case MEDIUM:
System.out.println("Medium level");
break;
case HIGH:
System.out.println("High level");
break;
}
}
}
Цикл через Enum
Тип enum має метод values(), який повертає масив усіх констант enum. Цей метод корисний, коли ви хочете прокрутити константи переліку:
for (Level myVar : Level.values()) {
System.out.println(myVar);
}
Різниця між Enum і Classes
Enum, як і клас, може мати атрибути та методи. Єдина відмінність полягає в тому, що константи enum є загальнодоступними, статичними та остаточними (незмінними – не можуть бути перевизначені).
Enum не можна використовувати для створення об’єктів, і він не може розширювати інші класи (але він може реалізовувати інтерфейси).
Чому і коли використовувати Enum?
Використовуйте переліки, якщо у вас є значення, які, як ви знаєте, не зміняться, як-от місяць, дні, кольори, колода карт тощо.
Введення користувача
Клас Scanner використовується для отримання введених даних користувача, і його можна знайти в пакеті java.util.
Щоб використовувати клас Scanner, створіть об’єкт класу та скористайтеся будь-яким із доступних методів, знайдених у документації класу Scanner. У нашому прикладі ми будемо використовувати метод nextLine(), який використовується для читання рядків:
import java.util.Scanner; // Import the Scanner class
class Main {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in); // Create a Scanner object
System.out.println("Enter username");
String userName = myObj.nextLine(); // Read user input
System.out.println("Username is: " + userName); // Output user input
}
}
Типи введення
У прикладі вище ми використали метод nextLine(), який використовується для читання рядків. Щоб прочитати інші типи, перегляньте таблицю нижче:
Method Description
nextBoolean() Reads a boolean value from the user
nextByte() Reads a byte value from the user
nextDouble() Reads a double value from the user
nextFloat() Reads a float value from the user
nextInt() Reads a int value from the user
nextLine() Reads a String value from the user
nextLong() Reads a long value from the user
nextShort() Reads a short value from the user
У прикладі нижче ми використовуємо різні методи для читання даних різних типів:
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in);
System.out.println("Enter name, age and salary:");
// String input
String name = myObj.nextLine();
// Numerical input
int age = myObj.nextInt();
double salary = myObj.nextDouble();
// Output input by user
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Salary: " + salary);
}
}
Примітка. Якщо ви введете неправильні дані (наприклад, текст у числовій введеній цифрі), ви отримаєте повідомлення про виняток/помилку (наприклад, "InputMismatchException").
Ви можете прочитати більше про винятки та способи обробки помилок у розділі «Винятки».
Клас ArrayList — це масив зі змінним розміром, який можна знайти в пакеті java.util.
Різниця між вбудованим масивом і ArrayList у Java полягає в тому, що розмір масиву не можна змінити (якщо ви хочете додати або видалити елементи до/з масиву, вам потрібно створити новий). Хоча елементи можна додавати та видаляти з ArrayList коли завгодно. Синтаксис також дещо відрізняється:
import java.util.ArrayList; // import the ArrayList class
ArrayList<String> cars = new ArrayList<String>(); // Create an ArrayList object
Додавання елементів
Клас ArrayList має багато корисних методів. Наприклад, щоб додати елементи до ArrayList, використовуйте метод add():
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
System.out.println(cars);
}
}
Доступ до елемента
Щоб отримати доступ до елемента в ArrayList, використовуйте метод get() і зверніться до номера індексу:
cars.get(0);
Змінити елемент
Щоб змінити елемент, використовуйте метод set() і зверніться до номера індексу:
cars.set(0, "Opel");
Видалити елемент
Щоб видалити елемент, використовуйте метод remove() і зверніться до номера індексу:
cars.remove(0);
Розмір ArrayList
Щоб дізнатися, скільки елементів містить ArrayList, скористайтеся методом розміру:
cars.size();
Цикл через ArrayList
Перегляньте елементи ArrayList за допомогою циклу for і скористайтеся методом size(), щоб вказати, скільки разів має виконуватися цикл:
public class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
for (int i = 0; i < cars.size(); i++) {
System.out.println(cars.get(i));
}
}
}
Ви також можете прокрутити список ArrayList за допомогою циклу for-each:
public class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
for (String i : cars) {
System.out.println(i);
}
}
}
Інші типи
Елементи в ArrayList насправді є об’єктами. У наведених вище прикладах ми створили елементи (об'єкти) типу "String". Пам’ятайте, що рядок у Java є об’єктом (а не примітивним типом). Щоб використовувати інші типи, такі як int, ви повинні вказати еквівалентний клас оболонки: Integer. Для інших примітивних типів використовуйте: Boolean для boolean, Character для char, Double для double тощо:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> myNumbers = new ArrayList<Integer>();
myNumbers.add(10);
myNumbers.add(15);
myNumbers.add(20);
myNumbers.add(25);
for (int i : myNumbers) {
System.out.println(i);
}
}
}
Сортування ArrayList
Іншим корисним класом у пакеті java.util є клас Collections, який містить метод sort() для сортування списків за алфавітом або числом:
import java.util.ArrayList;
import java.util.Collections; // Import the Collections class
public class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
Collections.sort(cars); // Sort cars
for (String i : cars) {
System.out.println(i);
}
}
}
Сортувати ArrayList цілих чисел:
import java.util.ArrayList;
import java.util.Collections; // Import the Collections class
public class Main {
public static void main(String[] args) {
ArrayList<Integer> myNumbers = new ArrayList<Integer>();
myNumbers.add(33);
myNumbers.add(15);
myNumbers.add(20);
myNumbers.add(34);
myNumbers.add(8);
myNumbers.add(12);
Collections.sort(myNumbers); // Sort myNumbers
for (int i : myNumbers) {
System.out.println(i);
}
}
}
У попередньому розділі ви дізналися про клас ArrayList. Клас LinkedList майже ідентичний ArrayList:
// Import the LinkedList class
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> cars = new LinkedList<String>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
System.out.println(cars);
}
}
ArrayList проти LinkedList
Клас LinkedList — це колекція, яка може містити багато об’єктів одного типу, як і ArrayList.
Клас LinkedList має ті самі методи, що й клас ArrayList, оскільки вони обидва реалізують інтерфейс List. Це означає, що ви можете додавати елементи, змінювати елементи, видаляти елементи та очищати список таким же чином.
Однак, незважаючи на те, що класи ArrayList і LinkedList можна використовувати однаково, вони побудовані дуже по-різному.
Як працює ArrayList
У класі ArrayList є звичайний масив. Коли елемент додається, він розміщується в масиві. Якщо масив недостатньо великий, замість старого створюється новий, більший масив, а старий видаляється.
Як працює LinkedList
LinkedList зберігає свої елементи в «контейнерах». Список містить посилання на перший контейнер, а кожен контейнер має посилання на наступний контейнер у списку. Щоб додати елемент до списку, елемент поміщається в новий контейнер, і цей контейнер зв’язується з одним з інших контейнерів у списку.
Коли використовувати
Використовуйте ArrayList для зберігання та доступу до даних і LinkedList для маніпулювання даними.
Методи LinkedList
У багатьох випадках ArrayList ефективніший, оскільки зазвичай потрібен доступ до випадкових елементів у списку, але LinkedList надає кілька методів для більш ефективного виконання певних операцій:
addFirst() Adds an item to the beginning of the list.
addLast() Add an item to the end of the list
removeFirst() Remove an item from the beginning of the list.
removeLast() Remove an item from the end of the list
getFirst() Get the item at the beginning of the list
getLast() Get the item at the end of the list
Статичні змінні
Статичні члени Статична змінна – це загальна змінна для всіх екземплярів класу, яка зберігається в об'єкті.
Об'єкти містять у собі статичні поля та методи.
class MyClass {
public static int field;
}
public static void main(String args[]) {
MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass();
MyClass.field = 2;
MyClass.field = 5;
}
Статичні методи та властивості
Статичними можуть бути члени та методи класу:
public class MyClass {
public static field;
public static method() {
System.out.println(“MyClass static method()”);
}
public static void main(String args[]) {
MyClass.field = 5;
MyClass.method();
}
Статичні методи не можуть звертатися до нестатичних полів.
Статичні члени не можуть бути віртуальними, перевизначеними й абстрактними.
Під час виконання коду Java можуть виникнути різні помилки: помилки кодування, зроблені програмістом, помилки через неправильне введення або інші непередбачені речі.
Коли виникає помилка, Java зазвичай зупиняється та генерує повідомлення про помилку. Технічний термін для цього: Java викличе виняток (викине помилку).
Java спробуй і впіймай
Інструкція try дозволяє вам визначити блок коду, який буде перевірено на помилки під час його виконання.
Інструкція catch дозволяє визначити блок коду, який буде виконано, якщо в блоці try станеться помилка.
Ключові слова спробувати та зловити поділяються на пари:
try {
// Block of code to try
}
catch(Exception e) {
// Block of code to handle errors
}
Якщо сталася помилка, ми можемо використати try...catch, щоб виявити помилку та виконати певний код для її обробки:
public class Main {
public static void main(String[ ] args) {
try {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]);
} catch (Exception e) {
System.out.println("Something went wrong.");
}
}
}
Finally
Інструкція finally дозволяє виконувати код після try...catch, незалежно від результату:
public class Main {
public static void main(String[] args) {
try {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]);
} catch (Exception e) {
System.out.println("Something went wrong.");
} finally {
System.out.println("The 'try catch' is finished.");
}
}
}
Ключове слово throw
Інструкція throw дозволяє створити настроювану помилку.
Інструкція throw використовується разом із типом винятку. У Java є багато типів винятків: ArithmeticException, FileNotFoundException, ArrayIndexOutOfBoundsException, SecurityException тощо:
public class Main {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
}
else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(15); // Set age to 15 (which is below 18...)
}
}
Класи-огортки забезпечують спосіб використання примітивних типів даних (int, boolean тощо) як об’єктів.
У таблиці нижче показано примітивний тип і еквівалентний клас оболонки:
Primitive Data Type Wrapper Class
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character
Іноді потрібно використовувати класи-обгортки, наприклад, коли працюєте з об’єктами колекції, такими як ArrayList, де не можна використовувати примітивні типи (список може зберігати лише об’єкти):
ArrayList<int> myNumbers = new ArrayList<int>(); // Invalid
ArrayList<Integer> myNumbers = new ArrayList<Integer>(); // Valid
Створення об'єктів-обгорток
Щоб створити об’єкт оболонки, використовуйте клас оболонки замість примітивного типу. Щоб отримати значення, ви можете просто надрукувати об’єкт:
public class Main {
public static void main(String[] args) {
Integer myInt = 5;
Double myDouble = 5.99;
Character myChar = 'A';
System.out.println(myInt);
System.out.println(myDouble);
System.out.println(myChar);
}
}
Оскільки ви зараз працюєте з об’єктами, ви можете використовувати певні методи для отримання інформації про конкретний об’єкт.
Наприклад, такі методи використовуються для отримання значення, пов’язаного з відповідним об’єктом оболонки: intValue(), byteValue(), shortValue(), longValue(), floatValue(), doubleValue(), charValue(), booleanValue() .
Цей приклад виведе той самий результат, що й приклад вище:
public class Main {
public static void main(String[] args) {
Integer myInt = 5;
Double myDouble = 5.99;
Character myChar = 'A';
System.out.println(myInt.intValue());
System.out.println(myDouble.doubleValue());
System.out.println(myChar.charValue());
}
}
Іншим корисним методом є метод toString(), який використовується для перетворення об’єктів-огорток у рядки.
У наступному прикладі ми перетворюємо Integer на String і використовуємо метод length() класу String для виведення довжини «рядка»:
public class Main {
public static void main(String[] args) {
Integer myInt = 100;
String myString = myInt.toString();
System.out.println(myString.length());
}
}
Ітератор
Ітератор — це об’єкт, який можна використовувати для циклічного перегляду колекцій, наприклад ArrayList і HashSet. Його називають «ітератором», тому що «ітерація» є технічним терміном для циклу.
Щоб використовувати ітератор, ви повинні імпортувати його з пакета java.util.
Отримання ітератора
Метод iterator() можна використовувати для отримання ітератора для будь-якої колекції:
// Import the ArrayList class and the Iterator class
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Make a collection
ArrayList<String> cars = new ArrayList<>();
cars.add("Volvo");
cars.add("BMW");
cars.add("Ford");
cars.add("Mazda");
// Get the iterator
Iterator<String> it = cars.iterator();
// Print the first item
System.out.println(it.next());
}
}
Перегляд колекції
Щоб прокрутити колекцію, використовуйте методи hasNext() і next() ітератора:
while(it.hasNext()) {
System.out.println(it.next());
}
Видалення елементів із колекції
Ітератори призначені для легкої зміни колекцій, які вони проходять. Метод remove() може видаляти елементи з колекції під час виконання циклу.
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(12);
numbers.add(8);
numbers.add(2);
numbers.add(23);
Iterator<Integer> it = numbers.iterator();
while(it.hasNext()) {
Integer i = it.next();
if(i < 10) {
it.remove();
}
}
System.out.println(numbers);
}
}
Примітка. Спроба видалити елементи за допомогою циклу for або for-each не спрацює належним чином, оскільки колекція змінює розмір у той самий час, коли код намагається виконати цикл.
Узагальнення дають змогу створювати відкриті типи, які перетворюються на закриті під час виконання. Ідентифікатор – це вказівник місця заповнення, замість якого підставляється будь-який тип.
Boxing-Unboxing
Узагальнення забезпечують більшу продуктивність, оскільки не відбувається операції «упакування-розпаковування» (boxing-unboxing).
class MyClass {
public T field;
public void method() {
System.out.println(field.getClass());
}
}
public static void main(String args[]) {
MyClass instance = new MyClass();
instance.method();
}
Узагальнення забезпечують безпеку типів, оскільки можуть містити лише типи, які задаються під час оголошення.
Загальні відомості про універсальні шаблони :
• Використовуйте універсальні типи для досягнення максимального рівня повторного використання коду, типу безпеки та продуктивності.
• Найчастішим випадком використання універсальних шаблонів є створення класів колекції.
• Можна створювати власні універсальні інтерфейси, класи та методи.
• Доступ універсальних класів до методів можна обмежити певними типами даних.
Колекції є одним з основних компонентів Java API і являють собою контейнери, які використовуються для зберігання та управління групами об’єктів. Це зручні та ефективні структури даних для роботи з наборами елементів.
У Java існує багатий набір класів та інтерфейсів, які надають різні типи колекцій. Вони дають змогу програмістам обирати найбільш підходящу структуру даних для конкретних завдань.
Основні типи колекцій у Java: List, Set, Queue і Map
У Java основні типи колекцій можна розділити на чотири категорії: List, Set, Queue і Map.
List являє собою впорядкований список, де елементи можуть повторюватися. Приклади класів List включають `ArrayList`, `LinkedList` і `Vector`.
Set – це колекція унікальних елементів, де кожен елемент може бути доданий тільки один раз. Приклади класів Set включають `HashSet`, `TreeSet` і `LinkedHashSet`.
Queue – колекція, яка працює за принципом “першим прийшов – першим вийшов” (FIFO – First-In-First-Out). Приклади класів Queue включають `LinkedList` і `PriorityQueue`.
Map – це колекція пар ключ-значення, де кожен ключ є унікальним. Приклади класів Map включають `HashMap`, `TreeMap` і `LinkedHashMap`.
Робота з колекціями: основні операції
Під час роботи з колекціями в Java виконуються такі основні операції:
Додавання елемента. Ми можемо додавати елементи в колекцію за допомогою методу `add()`. Наприклад:
`list.add(element)` додає елемент у список `list`,
`set.add(element)` додає елемент у множину `set`,
`queue.add(element)` додає елемент у чергу `queue`,
`map.put(key, value)` додає пару ключ-значення в карту `map`.
Отримання елемента. Отримати елементи з колекції можна за допомогою різних методів. Наприклад:
для списку `list` можна використовувати `list.get(index)` для отримання елемента за індексом,
для множини `set` використовується `set.contains(element)` для перевірки наявності елемента,
для черги `queue` застосовується `queue.peek()` для отримання першого елемента в черзі,
а для карти `map` потрібно використовувати `map.get(key)` для отримання значення за ключем.
Видалення елемента. Ми можемо видаляти елементи з колекції за допомогою методів `remove()` або `clear()`. Наприклад:
`list.remove(element)` видаляє елемент зі списку,
`set.remove(element)` видаляє елемент із множини,
`queue.poll()` видаляє і повертає перший елемент із черги,
`map.remove(key)` видаляє пару ключ-значення з карти за ключем.
Ітерація по колекції. Перебирати елементи колекції можна за допомогою циклу `for-each` або ітератора. Наприклад:
`for (Element element : list)` дає нам змогу перебирати елементи у списку `list`,
`for (Element element : set)` дає змогу перебирати елементи в множині `set`,
`for (Element element : queue)` дає змогу перебирати елементи в черзі `queue`,
`for (Entry entry : map.entrySet())` дає змогу перебирати пари ключ-значення в карті `map`.
Розмір колекції. Ми можемо дізнатися розмір колекції за допомогою методу`size()`. Наприклад:
`list.size()` повертає кількість елементів у списку,
`set.size()` повертає кількість елементів у множині,
`queue.size()` повертає розмір черги,
`map.size()` повертає кількість пар ключ-значення в карті.
Інші операції. Крім основних операцій, існують й інші корисні методи для роботи з колекціями, такі як сортування, пошук, фільтрація тощо. Ці методи доступні через відповідні класи та інтерфейси колекцій.
Інтерфейс Iterator забезпечує пересування колекцією й перебір її елементів.
Методи Iterator
hasNext() — повертає true, якщо є наступний елемент. Інакше повертає false.
next() — повертає наступний елемент. Породжує виняток NoSuchElementException, якщо такого немає.
remove() — видаляє поточний елемент. Породжує виняток IllegalStateException, якщо до цього не викликано метод next.
Порядок використання Iterator
Отримати ітератор початку колекції викликом методу iterator.
Використати цикл з попередньою перевіркою умови: доки hasNeмаxt повертає true.
Усередині циклу отримати наступний елемент викликом методу next і опрацювати отримане значення.
Для колекцій, які втілюють List, можна використати інтерфейс ListIterator.
Інтерфейс ListIterator розширює інтерфейс Iterator для забезпечення двонаправленого обходу списку та модифікації елементів.
Методи ListIterator
add(o) — вставляє об'єкт o у список перед елементом, який буде повернено наступним викликом next.
hasNext() — повертає true, якщо є наступний елемент. Інакше повертає false.
hasPrevious() — повертає true, якщо є попередній елемент. Інакше повертає false.
next() — повертає наступний елемент-об'єкт. Породжує виняток NoSuchElementException, якщо немає наступного елемента.
nextIndex() — повертає індекс (тип int) наступного елемента. Якщо такого немає, повертає довжину списку — кількість елементів у списку.
previous() — повертає попередній елемент-об'єкт. Проджує виняток NoSuchElementException, якщо такого немає.
previousIndex() — повертає індекс (тип int) попереднього елемента. Якщо попереднього елемента немає, повертає -1.
remove() — видаляє поточний елемент зі списку. Проджує виняток IllegalStateException, якщо до цього не було викликано next або previous.
set(o) — поточному елементу, повернутому останнім викликом next або previous, надає значення об'єкта o.
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("First element");
al.add("Second element");
al.add("Third element");
System.out.println(al);
System.out.println("--------------------------------------");
// за допомогою ітератора можемо бігати за нашим списком
Iterator<String> iterator = al.iterator();
// питаємо чи є наступний елемент у списку, якщо true, то буде реалізовано тіло while
while (iterator.hasNext()) {
// переходимо до наступного елемента у списку та його виводимо
String temp = iterator.next();
System.out.println(temp);
}
System.out.println("--------------------------------------");
// та ж дія, але через оптимізований ітератор під списки
ArrayList<String> states = new ArrayList<>();
states.add("First element");
states.add("Second element");
states.add("Third element");
ListIterator<String> listIter = states.listIterator();
while(listIter.hasNext()){
System.out.println(listIter.next());
}
System.out.println("--------------------------------------");
while(listIter.hasPrevious()){
System.out.println(listIter.previous());
}
}
}
Для того щоб об'єкти можна було порівняти і сортувати, вони повинні реалізувати параметризований інтерфейс Comparable.
Інтерфейс Comparable містить один єдиний метод int compareTo(T item), який порівнює поточний об'єкт з об'єктом, переданим як параметр.
Якщо цей метод повертає від'ємне число, то поточний об'єкт буде розташовуватися перед тим, який передається через параметр. Якщо метод поверне позитивне число, то, навпаки, після другого об'єкта. Якщо метод повертає нуль, значить, обидва об'єкти рівні.
Розглянемо приклад реалізації інтерфейсу Comparable:
Якщо клас з якоїсь причини не може реалізувати інтерфейс Comparable, або ж просто потрібен інший варіант порівняння, використовується інтерфейс Comparator.
Інтерфейс містить метод int compare(T o1, T o2), який має бути реалізований класом, що реалізує компаратор.
Метод compare повертає числове значення - якщо воно від'ємне, то об'єкт o1 передує об'єкту o2, інакше - навпаки. А якщо метод повертає нуль, то об'єкти рівні.
Для застосування інтерфейсу нам спочатку треба створити клас компаратора, який реалізує цей параметризований інтерфейс.
Розглянемо приклад використання інтерфейсу Comparator:
Клас тварини
public class Animal{
int widh;
int high;
String bread;
String color;
public Animal(int widh, int high, String bread, String color) {
this.widh = widh;
this.high = high;
this.bread = bread;
this.color = color;
}
public String toString() {
return this.widh + " " + this.high + " " + this.bread + " " + this.color;
}
}
class ComparatorByPrice implements Comparator {
public int compare (Object o1, Object o2) {
return ((Animal)o1).widh - ((Animal)o2).widh;
}
}
class ComparatorBySpeed implements Comparator {
public int compare (Object o1, Object o2) {
return ((Animal)o1).high - ((Animal)o2).high;
}
}
class ComparatorByColor implements Comparator {
public int compare (Object o1, Object o2) {
return ((Animal)o1).color.compareTo(((Animal)o2).color);
}
}
Клас для запуску
public class Main {
public static void main(String[] args) {
Animal animal1 = new Animal(190, 40, "Pitbul", "Red");
Animal animal2 = new Animal(140, 50, "Layka", "Black");
Animal animal3 = new Animal(185, 100, "Taxa", "White");
Animal[] c = {animal1, animal2, animal3};
Arrays.sort(c, new ComparatorByPrice());
for (Animal temp : c) {
System.out.println(temp);
}
System.out.println();
Arrays.sort(c, new ComparatorBySpeed());
for (Animal temp : c) {
System.out.println(temp);
}
System.out.println();
Arrays.sort(c, new ComparatorByColor());
for (Animal temp : c) {
System.out.println(temp);
}
}
}