Лабораторна робота 1: Базовий синтаксис Java

Теоретичний матеріал

Під час розроблення мови Java було взято за основу синтаксис мов С і C++, тому багато аспектів синтаксису мови здадуться вам знайомими.

Коментарі

У Java, як і в C, існують однорядкові та блокові коментарі. Однак, крім цього, згідно з конвенцією Oracle, існують інші види коментарів: copyright-блок угорі, doc-коментарі, TODO-коментарі, коментарі після statement`ів, коментарі для коментування коду. Ознайомтеся з прийнятими правилами використання коментарів, на захисті лабораторних вони будуть вимагатися в обов'язковому порядку, згідно з прийнятими конвенціями.

package ai231.ivanov;

/**
 * Це спеціальний коментар для документування (Doc comment).
 * За допомогою спеціальної утиліти (javadoc), такі коментарі можна 
 * перетворити на HTML-сторінки,
 * которые вместе создают документацию к вашей программе.
 * Для зручності, тут можна використовувати спеціальні посилання {@link 
 * Main} та <i>HTML-теги</i>.
 */
public class Main {

    /**
     * Цей метод є "точкою входу" додатка. У проєкті може бути тільки один 
     * метод з такою сигнатурою
     * @param args аргументи під час запуску програми
     */
    public static void main(String[] args) {

        // Це однорядковий коментар (single line comment)

        /*
         * Це коментар у вигляді блоку (block comment)
         */

        // TODO: це спеціальний TODO-коментар. Тут можна описати, що потрібно доробити на якійсь ділянці коду
        // FIXME: це теж TODO-коментар, зазвичай тут дрібні баги і що потрібно виправити на цій ділянці коду

        // TODO:2023-09-03:NickGodov: дописати виведення даних у файл

        int my_variable = 5;            /* Коментарі після statement повинні бути вирівняні зліва */
        int my_other_variable = 999;    /* за допомогою табуляції */

        // Якщо потрібно закоментувати код, то кожен рядок коментується однорядковим коментарем
        // int my_old_variable = 100;
        // int my_other_old_variable = 200;

        // Перед коментарем прийнято залишати порожній рядок
        int number = 924;
    }
}

Змінні

Змінні чутливі до регістру (variable і Variable - дві різні змінні), можуть бути нескінченної довжини, складатися з літер юнікоду і цифр юнікоду, символів _ і $. Перший символ змінної може бути літерою, символом _ або $ (використовувати _ або $ першим символом Вкрай НЕ РЕКОМЕНДУЄТЬСЯ, вони існують для спеціальних ситуацій, які нас зараз не цікавлять, тож вважайте, що починатися змінна може тільки з літери юнікоду). Вкрай не рекомендується використовувати літери національних алфавітів, кирилицю, трансліт. Тільки латинські літери, назви англійською. Також, назви змінних не повинні збігатися зі списком зарезервованих слів, що представлений нижче.

Крім ключових слів у Java існують три літерали: null, true, false, які не належать до ключових і зарезервованих слів, а також зарезервоване слово var, значення якого залежить від його позиції в коді. Наведений нижче блок коду дасть вам загальне уявлення про те, як треба називати змінні.

int spd         = 25;   // ПОГАНО: Можна, але не рекомендується, оскільки назва не інформативна
int carminspd   = 25;   // ПОГАНО: Не економте на назвах змінних!
int carMinSpeed = 25;   // ДОБРЕ: Назва змінної говорить сама за себе

int s = 0; // МОЖНА: однобуквені допускаються, тільки якщо це якісь короткоживучі змінні

int speed = 150;    // ДОБРЕ: Нормально, зрозуміло, що змінна відповідає за швидкість
int Speed = 150;    // ПОГАНО: Вкрай не рекомендується, змінні не повинні починатися з великої літери
int SPEED = 150;    // ПОГАНО: Вкрай не рекомендується, повністю великими літерами пишуться константи

const int MIN_SPEED = 25; // НЕ МОЖНА: у Java const не використовується (хоча це зарезервоване слово)
final int MIN_SPEED = 25; // ДОБРЕ: у Java для констант використовується final

int моя_змінна         = 356;     // ПОГАНО: Тільки латиниця
int DŽDžDzȯȺώϷЂ           = 145;     // ПЛОХО: Только латиница
int moya_zminna        = 29;      // ПОГАНО: Трансліт - це повний моветон, тільки англійська!

int $myvar = 100;   // ПОГАНО: Теоретично можливо, але НЕ РЕКОМЕНДУЄТЬСЯ
int _myvar = 100;   // ПОГАНО: Теоретично можливо, але НЕ РЕКОМЕНДУЄТЬСЯ
int 2pac   = 0;     // НЕ МОЖНА: з цифри починати не можна
int %d     = 5;     // НЕ МОЖНА: з інших знаків починати не можна
int 'f'    = 5;     // НЕ МОЖНА: з лапок починати не можна

// Якщо назва змінної складається з двох слів
int max_speed       = 150;  // ПОГАНО: Використовувати _ для відокремлення слів не в константах не рекомендується
int MaxSpeed        = 150;  // ПОГАНО: Вкрай не рекомендується, змінні не повинні починатися з великої літери
int maxSpeed        = 150;  // ДОБРЕ: Ось так нормально, використовується lowerCamelCase
final int MAX_SPEED = 150;  // ДОБРЕ: Константи пишуться капсом, кожне слово відокремлюється _

Типи даних

У мові Java існують примітивні типи (аналогічні типам даних у C) і посилальні (або об'єктні) типи даних. На даний момент нас цікавлять тільки примітивні типи даних.

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

Загалом існують вісім примітивних типів даних: int, long, short, byte, double, float, char, boolean. Їх дуже легко запам'ятати:

  • 4 типи для цілих чисел ("коротке short", "середнє int", "довге long" і байт);
  • 2 типи для чисел із плаваючою комою (стара парочка double і float);
  • 2 "спеціальні" типи - символ і булевий тип.

Оператори розгалуження

Оператори розгалуження в C і Java практично ідентичні

int a = 5;
int b = 4;
int min;

// Так потрібно оформляти звичайний if
if (a >= b) {
    min = b;
}

// Так потрібно оформляти if-else
if (a >= b) {
    min = b;
} else {
    min = a;
}

// Так потрібно оформляти if-else if-else
if (a > b) {
    min = b;
} else if (a < b) {
    min = a;
} else {
    min = a;
}

// У Java використовується тернарний оператор
min = (a >= b) ? b : a;

// Це рівнозначно такому виразу
if (a >=b) {
    min = b;
} else {
    min = a;
}

// Так оформляється switch
switch (a) {
    case 1:
        // щось робимо
        break;
    case 2:
        // робимо щось інше
        break;
    default:
        // це виконується в тому разі, якщо жоден із кейсів не виконався
}

Цикли

Робота з циклами в Java мало чим відрізняється від мови C

int progression = 0;

// Так оформляється for
for (int i=0; i < 5; i++) {
    progression +=i;
}

// ПОГАНО: так оформляти цикли не рекомендується
for (int i=0; i < 5; i++) progression +=i;

// МОЖЛИВО: якщо тіло циклу складається з одного statement'а, то можна опустити фігурні дужки
for (int i=0; i < 5; i++)
    progression +=i;

// Порожній for
for (int j=0; j < 10; j++);

// Так оформляється while
int iterator = 0;
while (iterator < 10) {
    // робимо щось у циклі
    iterator++;
}

// Так оформляється do-while
int loops = 10;
do {
    // щось робимо
    loops--;
} while (loops > 0);

// Також, у Java є аналог foreach
int[] array = { 1, 2, 3, 4, 5 };
int sum = 0;
for(int i : array) {
    sum += i;
}

// Цей же цикл можна представити звичайним for`ом
for(int i = 0; i < 5; i++) {
    sum += array[i];
}

Масиви

Робота з масивами в Java дещо відрізняється від роботи з масивами в C, в основному, через механізм виділення пам'яті під масиви.

// Оголошення масивів

/*
 * ДОБРЕ: згідно з усіма угодами щодо коду та різними рекомендаціями, квадратні дужки ставляться ПІСЛЯ ТИПУ ДАНИХ
 */
int[] goodArray;

/*
 * ПОГАНО: компілятор не видасть помилку, але такий синтаксис робить код менш читабельним
 */
int badArray[];

/*
 * НЕ МОЖНА: при оголошенні масиву не можна вказати його розмірність.
 * Java не виділить пам'ять, поки масив не буде ініціалізовано
 */
int[5] anotherBadArray;

// Оголошення багатовимірних масивів

int [][] twoDimensionalArray;
int [][][] threeDimensionalArray;

// Ініціалізація масивів

goodArray = new int[10];    // Ініціалізуємо масив із 10 елементами
goodArray[0] = 15;          // Присвоюємо значення першому елементу масиву
goodArray[1] = 25;          // Присвоюємо значення другому елементу масиву

twoDimensionalArray = new int [5][4];   // Двовимірний масив 5х4
twoDimensionalArray[0] = new int[4];
twoDimensionalArray[1] = new int[8];    // ПОГАНО: Компілятор проковтне, але за фактом виділиться місце всього під 4 інти
twoDimensionalArray[0][0] = 1; // Присвоюємо значення
twoDimensionalArray[1][5] = 5; // НЕ МОЖНА: Компілятор видасть помилку

System.out.print(twoDimensionalArray[1][6]); // НЕ МОЖНА: Компілятор видасть помилку

// Оголошення з ініціалізацією

int[] quickArray = {1, 2, 3 ,4};    // Оголошуємо й одразу заповнюємо дані. Компілятор виділить місце під 4 інти
quickArray[5] = 6;                  // НЕ МОЖНА: Компілятор видасть помилку, оскільки індекс виходить за межі масиву

int[][] quick2DArray = {
        {1 ,2 ,3},
        {1, 3, 4}
};

Методи

Оскільки Java є об'єктно-орієнтованою мовою, функції тут називаються методами (наразі ми вважатимемо, що методи і функції виконують одну й ту саму роль, але методи можуть перебувати тільки всередині класів).

/*
 * Синтаксис функції:
 * [1-модифікатори доступу] [2-тип значення, що повертається] [3-ім'я]([4-аргументи]) [5-список виключень] {
 *     6- тіло функції
 * }
 *
 * 1 - модифікатори доступу: на даний момент вони нас не цікавлять, можна нічого не писати або писати private
 * 2 - тип значення, що повертається - тип даних або void, якщо функція нічого не повертає
 * 3 - обмеження як і на імена змінних, але є додаткові правила найменування, про них нижче
 * 4 - список аргументів через кому. Наприклад (int a, double b). Якщо немає аргументів - порожні дужки
 * 5 - виключення поки не розглядаємо, якщо їх немає, то просто нічого не пишуть
 * 6 - тіло функції, у ньому відбувається виконання функції. Якщо є тип даних, що повертається - має бути return
 */
private int findMinimum(int a, int b) {
        int min;

        min = (a < b) ? a : b;
        return min;
        }

/*
 * Назва методу починається з маленької літери, якщо кілька слів - використовується lowerCamelCase.
 * Перше слово має бути дієсловом (тому що метод, як правило, "щось робить"), інші слова можуть бути
 * прикметниками, іменниками і тд. Символ _ вкрай бажано не використовувати (крім юніт-тестів)
 */

// ДОБРЕ: з маленької літери, перше слово - дієслово
private void drawCircle() {}

// ПОГАНО: Символи $ і _ не використовуємо
private void $er () {}

// ПОГАНО: використовуйте camelCase для назви методів
private void draw_circle () {}

// ПОГАНО: назва методу має починатися з маленької літери
private void Draw() {}

// ПОГАНО: перше слово має бути дієсловом
private void circle() {}