Операції над об’єктами. Операція присвоювання об’єктів. Операції порівняння об’єктів

Операції над об’єктами. Операція присвоювання об’єктів. Операції порівняння об’єктів


Зміст


1. Які операції можна застосовувати над об’єктами в мові програмування Java?

Мова програмування Java надає широкий спектр операцій, які можна застосовувати для примітивних типівданих та для об’єктів.

Для об’єктів можна застосовувати наступні операції:

  • присвоєння =;
  • порівняння на рівність ==;
  • порівняння на нерівність !=.

2. Як працює операція присвоювання об’єктів ‘=’? Загальна форма

 Операція присвоювання об’єктів має наступну загальну форму

obj1 = obj2;

де

  • obj1, obj2 – посилання на об’єкти, що мають однаковий тип (клас). При присвоюванні об’єктів значення посилання на об’єкт obj2 присвоюється посиланню obj1. Фактично, присвоюються тільки посилання, тобто копіюється посилання з одного місця в інше. Після виконання присвоювання, обидва посилання посилаються на одну й туж область пам’яті (об’єкт).

3. Яка відмінність між присвоюванням (=) змінних примітивних типів та присвоюванням об’єктів?

Відмінність між присвоюванням змінних примітивних типів та об’єктів полягає у наступному:

  • при присвоюванні змінних примітивних типів копіюється значення однієї змінної в іншу. При цьому змінні розміщуються в різних ділянках пам’яті. Зміна значення однієї змінної не призведе до зміни значення іншої змінної;
  • при присвоюванні об’єктів, копіюється тільки посилання на об’єкт а не значення цього об’єкту. Тобто, після виконання присвоювання об’єктів, посилання на ці об’єкти вказують на одну й ту ж ділянку пам’яті. Після присвоювання, зміна даних об’єкту за одним посиланням призведе до зміни даних в іншому посиланні на об’єкт, тому що посилання на об’єкти посилаються на одну й туж ділянку пам’яті.



4. Які помилки можуть виникнути при присвоюванні посилань на об’єкти?

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

5. Приклади використання оператора присвоювання = для присвоювання об’єктів класів

Приклад 1. Нехай задано клас з іменем SomeClass

// деякий клас
class SomeClass {
    // внутрішні дані класу
    int d;
    float f;
    char c;

    // конструктор класу
    SomeClass(int d, float f, char c) {
        this.d = d;
        this.f = f;
        this.c = c;
    }
}

Нижче демонструється присвоювання об’єктів цього класу та демонстрація доступу до тієї самої ділянки пам’яті:

// створення об'єкту obj1
SomeClass obj1 = new SomeClass(5, 3.8f, 'z');

// оголошення об'єкту obj2 класу SomeClass, для якого не виділена пам'ять
SomeClass obj2 = null;

// присвоювання посилань на об'єкти
obj2 = obj1; // посилання на об'єкти вказують на одну й туж ділянку пам'яті

int d = obj2.d; // d = 5
d = obj1.d; // d = 5

float f = obj2.f; // f = 3.8
f = obj1.f; // f = 3.8

char c = obj2.c; // c = 'z'
c = obj1.c; // c = 'z'

obj1.d = 280;
d = obj2.d; // d = 280

obj2.f = 7.777f;
f = obj1.f; // f = 7.777

Приклад 2. Сортування масиву об’єктів методом вставки. У прикладі демонструється обмін між посиланнями на об’єкт типу Data.

Задано клас Data, що містить одну внутрішню змінну value та пояснення message до неї типу String. Реалізувати сортування даних за спаданням значення value методом вставки.

Реалізація класу Data наступна:

// оголошення класу Data
class Data {
    // дані класу
    int value;
    String message;

    // метод, що встановлює нові значення у внутрішні змінні класу
    void Set(int val, String msg) {
        value = val;
        message = msg;
    }
}

Використання масиву об’єктів типу Data може бути, наприклад, таким

// оголошення масиву об'єктів
Data[] D = new Data[10]; // виділення пам'яті для масиву типу Data в цілому
Data tmp; // додаткове посилання типу Data

// виділення пам'яті для кожного об'єкту
for (int i=0; i<D.length; i++)
    D[i] = new Data();

// заповнення масиву довільними значеннями
D[0].value = 5;
D[0].message = "value = 5";
D[1].value = 3;
D[1].message = "value = 3";
D[2].value = 7;
D[2].message = "value = 7";
D[3].value = 8;
D[3].message = "value=8";
D[4].value = 9;
D[4].message = "value => 9";
D[5].value = 10;
D[5].message = "value = 10";
D[6].value = 4;
D[6].message = "value = 4";
D[7].value = 6;
D[7].message = "value => 6 ";
D[8].value = 7;
D[8].message = "value = 7";
D[9].value = 2;
D[9].message = "value = two";

// сортування масиву в порядку спадання
for (int i=0; i<D.length-1; i++)
    for (int j=i; j>=0; j--)
        if (D[j].value<D[j+1].value) {
            // обмін місцями - обмінюються тільки посилання на об'єкт
            tmp = D[j]; // використовується додаткове посилання tmp
            D[j] = D[j+1];
            D[j+1] = tmp;
        }

// Виведення масиву
for (int i=0; i<D.length; i++)
    System.out.println("D["+i+"]: value = " + D[i].value + "; message" + D[i].message);

Як видно з вищенаведеного прикладу, між об’єктами D[j] та D[j+1] здійснюється обмін посиланнями на об’єкт класу, а не значеннями даних цих об’єктів. Використання посилань при такому обміні є ефективним, якщо екземпляр класу (об’єкт) містить велику кількість даних. Адже обмін двох посилань виконується набагато швидше ніж обмін усіх даних класу.

На екран буде виведено наступний результат:

D[0]: value = 10; messagevalue = 10
D[1]: value = 9; messagevalue => 9
D[2]: value = 8; messagevalue=8
D[3]: value = 7; messagevalue = 7
D[4]: value = 7; messagevalue = 7
D[5]: value = 6; messagevalue => 6
D[6]: value = 5; messagevalue = 5
D[7]: value = 4; messagevalue = 4
D[8]: value = 3; messagevalue = 3
D[9]: value = 2; messagevalue = two

Якщо реалізувати обмін даними в класі, то наступний код циклу сортування буде виконуватись довше ніж попередній:

// цей код виконується повільніше
String msg;
int val;

for (int i=0; i<D.length-1; i++)
    for (int j=i; j>=0; j--)
        if (D[j].value<D[j+1].value) {
            // обмін місцями даних об'єктів - виконується повільніше
            val = D[j].value;
            D[j].value = D[j+1].value;
            D[j+1].value = val;
            msg = D[j].message;
            D[j].message = D[j+1].message;
            D[j+1].message = msg;
        }

6. Чи можна присвоювати об’єкти різних класів?

Ні, не можна. При присвоюванні об’єктів різних класів компілятор Java видає помилку з повідомленням:

Type mismatch: cannot convert from SomeClass to SomeClass2

7. Яким чином працює операція присвоювання об’єктів, які містять вкладені об’єкти?

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

8. Операція порівняння об’єктів ==. Приклад

При порівнянні об’єктів порівнюються значення посилань. Результат порівняння true, якщо посилання мають однакові значення, тобто вони посилаються на один і той самий об’єкт.

Нехай задано клас DayWeek, який реалізує день тижня

// клас день тижня
class DayWeek {
    int day;   

    DayWeek(int day) {
        if ((day>=1)&&(day<=7))
            this.day = day;
    }
}

У нижченаведеному прикладі відбувається порівняння об’єктів класу типу DayWeek. Результат true встановлюється тільки тоді, коли значення посилань на об’єкти класу є рівні.

DayWeek dw = new DayWeek(5);
DayWeek dw2= null;
boolean b;

b = dw==dw2; // b = false
dw2 = dw; // dw2 і dw є рівні між собою
b = dw==dw2; // b = true

// оголошення посилань на різні ділянки пам'яті
DayWeek dw3 = new DayWeek(3);
DayWeek dw4 = new DayWeek(3);

if (dw3==dw4) 
    b = true;
else
    b = false; // b = false

9. Операція порівняння об’єктів !=. Приклад

Операція != (не рівне) повертає false, якщо значення посилань на об’єкти класу різняться між собою. Операція працює так само як і операція порівняння на рівність == об’єктів класу.

Нехай задано клас Circle, який реалізує коло на координатній площині

// клас, що реалізує коло
class Circle {
    double x, y;
    double radius;

    // конструктор
    Circle() {
        radius = 1;
        x = y = 0;
    }    
}

Нижче демонструється використання операції != для порівняння об’єктів

// оголошення об'єктів класу Circle
Circle c1 = new Circle(); // c1 - посилання на об'єкт класу Circle
Circle c2 = new Circle(); // c2 - посилання на об'єкт класу Circle
c2.radius = 2.5;
boolean b;

b = c1!=c2; // b = true: посилання c1 та c2 мають різні значення
c2 = c1;
b = c1!=c2; // b = false: посилання c1, c2 мають однакове значення


Зв’язані теми