Типи, String і різниця між == та equals
У Java два види типів: примітиви (int, long, double, boolean) і посилальні (класи, масиви, String, обгортки Integer, Boolean). Примітив зберігає значення, посилання — адресу об’єкта, тому воно може бути null.
== проти equals. Для примітивів == порівнює значення. Для об’єктів == порівнює посилання (чи це той самий об’єкт), а equals — вміст, якщо клас його перевизначив.
String a = "qa";
String b = new String("qa");
a == b; // false: різні об’єкти
a.equals(b); // true: однаковий текст
Літерали рядків потрапляють у пул, тому "qa" == "qa" завжди true, але рядки, створені під час виконання (з відповіді API, конкатенацією змінних, через new String), — окремі об’єкти, тож на == покладатися не можна. У тестах рядки завжди порівнюють через equals (або через assert-бібліотеку), а для можливого null — через Objects.equals(a, b).
Пастки для автоматизатора:
- Обгортки:
Integer зі значеннями −128…127 кешуються, тому == «працює» для малих чисел і ламається для великих. Порівнюйте через equals або розпакуйте в int.
- Розпакування
null у примітив кидає NullPointerException: int id = response.getId();, якщо поле — Integer зі значенням null.
- Гроші й точні дробові значення —
BigDecimal із рядкового конструктора (new BigDecimal("0.10")). double дає 0.1 + 0.2 != 0.3. Порівнюйте через compareTo: equals вважає 2.0 і 2.00 різними.
Сучасна Java для тестів: var, enum, record, текстові блоки
Поточна LTS-версія Java — 25 (раніше 21, 17, 11). Нові проєкти автоматизації варто починати на LTS і користуватися можливостями, які прибирають шаблонний код.
- enum — фіксований набір значень: браузери, оточення, ролі. Помилку в назві видно під час компіляції, а
switch по enum виразно перелічує варіанти.
enum Browser { CHROME, FIREFOX, EDGE }
Browser b = Browser.valueOf(System.getProperty("browser", "chrome").toUpperCase());
valueOf кидає IllegalArgumentException для невідомого імені — це швидка й зрозуміла відмова на старті, а не дивна поведінка посеред прогону.
- record (Java 16) — незмінний носій даних: компілятор додає конструктор, акцесори
email(), equals, hashCode, toString.
record Credentials(String email, String password) {}
Зручно для тестових даних і параметрів. Record не можна успадкувати й не можна змінити після створення; Jackson (2.12+) вміє читати й писати records.
- var (Java 10) — виведення типу локальної змінної:
var users = new ArrayList<User>();. Тип лишається статичним; var не для полів і параметрів. Не зловживайте, коли тип неочевидний із правої частини.
- Текстові блоки (Java 15) — багаторядкові рядки в потрійних лапках, зручні для JSON-тіл і SQL:
String body = """
{"email": "a@example.com", "role": "admin"}
""";
- Pattern matching для instanceof (
o instanceof User u) і switch-вирази скорочують перевірки типів.
Усе це лише синтаксис: на швидкість тестів не впливає, але робить код тестових даних коротшим і безпечнішим.