НОУ ІНТУІТ, Лекція, Типи даних
Посилальні типи
Отже, вираз посилання типу має значення або null або посилання, що вказує на деякий об'єкт у віртуальній пам'яті JVM .
Об'єкти та правила роботи з ними
Об'єкт (object) – це екземпляр деякого класу, або екземпляр масиву. Масиви докладно розглядатимуться у відповідній лекції. Клас – це опис об'єктів однакової структури, і якщо у програмі такий клас використовується, то опис є у єдиному екземплярі. Об'єктів цього класу може бути зовсім, а може бути створено скільки завгодно багато.
Якщо конструктор відпрацював успішно, вираз new повертає посилання на створений об'єкт. Це посилання можна зберегти в змінній, передати як аргумент у будь-який метод або використовувати іншим способом. JVM завжди займається підрахунком збережених посилань на кожен об'єкт. Як тільки виявляється, що посилань більше немає, такий об'єкт призначається для знищення збирачем сміття (garbage collector). Відновити посилання на такий "втрачений" об'єкт неможливо.
Посилань на об'єкт-точку (1,2) більше немає, доступ до нього втрачено і він незабаром буде знищений збирачем сміття.
Будь-який об'єкт породжується лише із застосуванням ключового слова new. Єдиний виняток - екземпляри класу String. Записуючи будь-який рядковий літерал, ми автоматично породжуємо об'єкт цього класу. Оператор конкатенації + , результатом якого є рядок, також неявно породжує об'єкти без ключового слова new .
При виконанні цього виразу буде створено три об'єкти класу String. Два об'єкти породжуються рядковими літералами, третій представлятиме результат конкатенації.
Операція створення об'єкта – одна з найбільш ресурсоємних у Java.Тому слід уникати непотрібних породжень. Оскільки під час роботи з рядками їх може створюватися чимало, компілятор, зазвичай, намагається оптимізувати такі висловлювання. У розглянутому прикладі, оскільки всі операнди є константами часу компіляції, компілятор сам здійснить конкатенацію і вставить в код результат, скоротивши таким чином кількість створюваних об'єктів до одного.
Крім того, у версії Java 1.1 була введена технологія reflection, яка дозволяє звертатися до класів, методів та полів, використовуючи лише їх ім'я в текстовому вигляді. З її допомогою також можна створити об'єкт без ключового слова new, проте ця технологія досить специфічна, застосовується в окремих випадках, а крім того, досить проста і тому в даному курсі не розглядається. Все ж таки наведемо приклад її застосування:
Об'єкт завжди " пам'ятає " , якого класу він був породжений. З іншого боку, як зазначалося, можна посилатися об'єкт, використовуючи посилання іншого типу. Наведемо приклад, який ще багато разів використовуватимемо. Спочатку опишемо два класи, Parent та його спадкоємець Child:
Поки що нам не потрібно визначати будь-які поля чи методи. Далі оголосимо змінну одного типу та проініціалізуємо її значенням іншого типу:
Тепер змінна типу Parent вказує на об'єкт, породжений класом Child .
Над значеннями посилань можна проводити наступні операції:
- звернення до полів та методів об'єкта
- оператор instanceof (повертає булеве значення)
- операції порівняння == і != (повертають бульова значення)
- оператор приведення типів
- оператор з умовою? :
- оператор конкатенації з рядком +
Звернення до полів та методів об'єкта можна назвати основною операцією над посиланнямивеличинами. Здійснюється вона за допомогою символу. (крапка). Приклади її застосування наводяться.
Результатом буде true. Таким чином, оператор stanceof спирається не на тип посилання, а на властивості об'єкта, на який вона посилається. Але цей оператор повертає справжнє значення як для типу, від якого був породжений об'єкт. Додамо до вже оголошених класів ще один:
Тепер заведемо змінну нового типу:
У першому рядку оголошується змінна типу Parent, яка ініціалізується посиланням на об'єкт, породжений від ChildOfChild. У другому рядку оператор instanceof аналізує сумісність посилання типу Parent з класом Child , причому об'єкт, що задіяний, не породжений ні від першого, ні від другого класу. Тим не менш, оператор поверне true, оскільки клас, від якого цей об'єкт породжений, успадковується від Child.
Додамо ще один клас:
І знову оголосимо змінну типу Parent:
Змінна p має тип Parent , отже, може посилатися об'єкти типу Child чи Child2 . Оператор stanceof допомагає розібратися в ситуації:
Для посилання, що дорівнює null , оператор instanceof завжди поверне значення false .
З вивченням властивостей об'єктної моделі Java ми повертатимемося до алгоритму роботи оператора в стані.
Оператори порівняння == і != перевіряють рівність (або нерівність) об'єктних величин саме за посиланням. Однак часто потрібне альтернативне порівняння – за значенням. Порівняння за значенням має справу з поняттям стан об'єкта. Сам зміст цього висловлювання у ООП, що стосується реалізації Java, то стан об'єкта зберігається у його полях. При порівнянні за посиланням ні тип об'єкта, ні значення його полів не враховуються, true повертається лише в тому випадку, якщо обидва посиланнявказують на той самий об'єкт.
Перше порівняння виявилося істинним, оскільки змінна p2 посилається той самий об'єкт, як і p1 . Друге ж порівняння хибно, незважаючи на те, що змінна p3 посилається на об'єкт-точку з такими ж координатами. Однак це інший об'єкт, який був породжений іншим виразом new.
Якщо один з аргументів оператора == дорівнює null, а інший – ні, то значення такого виразу буде false. Якщо ж обидва операнда null, то результат буде true.
Для коректного порівняння за значенням існує спеціальний метод equals, який буде розглянуто пізніше. Наприклад, рядки можна порівнювати так:
Операція з умовою? : працює як і може приймати другий і третій аргументи, якщо вони обидва одночасно посилання типу. Результат такого оператора також матиме об'єктний тип.