KNOW INTUIT, Лекция, Типове данни

Референтни типове

Така че изразът на референтен тип е или нула, или е референция, сочеща към някакъв обект във виртуалната памет на JVM.

Обекти и правила за работа с тях

Обектът е екземпляр на някакъв клас или екземпляр на масив. Масивите ще бъдат разгледани подробно в съответната лекция. Класът е описание на обекти с еднаква структура и ако такъв клас се използва в програма, тогава описанието присъства в един екземпляр. Обекти от този клас може изобщо да не съществуват, но могат да бъдат създадени произволно голям брой.

Ако конструкторът е успешен, тогава новият израз връща препратка към създадения обект. Тази препратка може да бъде съхранена в променлива, предадена като аргумент на метод или използвана по друг начин. JVM винаги е заета с преброяването на съхранените препратки към всеки обект. Веднага след като се установи, че няма повече препратки, такъв обект е предназначен за унищожаване от боклукчия. Невъзможно е да се възстанови връзка към такъв "загубен" обект.

Точковият обект (1,2) вече не се препраща, изгубен е и скоро ще бъде изтрит.

Всеки обект се генерира само с помощта на ключовата дума new. Единственото изключение са екземплярите на класа String. Когато пишем всеки низов литерал, ние автоматично генерираме обект от този клас. Операторът за конкатенация +, който води до низ, също имплицитно създава обекти, без да използва ключовата дума new.

Когато този израз се изпълни, ще бъдат създадени три обекта от клас String. Два обекта се генерират от низови литерали, третият ще представлява резултата от конкатенацията.

Операцията за създаване на обект е една от най-ресурсоемките в Java.Следователно трябва да се избягват ненужни поколения. Тъй като може да има доста от тях при работа с низове, компилаторът обикновено се опитва да оптимизира такива изрази. В горния пример, тъй като всички операнди са константи по време на компилиране, самият компилатор ще свърже и вмъкне резултата в кода, като по този начин ще намали броя на създадените обекти до един.

В допълнение, Java 1.1 въведе технологията за отразяване, която ви позволява да осъществявате достъп до класове, методи и полета, като използвате само тяхното текстово име. Може да се използва и за създаване на обект без ключовата дума new, но тази технология е доста специфична, използва се в редки случаи, а освен това е доста проста и затова не се разглежда в този курс. Ето обаче пример за използването му:

Един обект винаги "помни" от кой клас е извлечен. От друга страна, както вече беше споменато, е възможно да се препрати към обект, използвайки друг тип препратка. Ето един пример, който ще използваме многократно. Нека първо опишем два класа, родител и неговия наследник дете:

Засега не е необходимо да дефинираме никакви полета или методи. След това декларираме променлива от един тип и я инициализираме със стойност от друг тип:

Сега променливата тип Parent сочи към обект, извлечен от класа Child.

Можете да извършвате следните операции върху референтни стойности:

  • достъп до полета и методи на обект
  • оператор instanceof (връща булева стойност)
  • оператори за сравнение == и != (връщат булева стойност)
  • каст оператор
  • условен оператор? :
  • оператор за конкатенация на низове +

Достъпът до полетата и методите на даден обект може да се нарече основна операция върху референтни обекти.количества. Извършва се със символа . (точка). Ще бъдат дадени примери за неговото приложение.

Резултатът ще бъде верен. Така операторът instanceof разчита не на типа на препратката, а на свойствата на обекта, към който препраща. Но този оператор връща истинска стойност не само за типа, от който е генериран обектът. Нека добавим още един клас към вече декларираните класове:

Сега нека създадем променлива от нов тип:

Първият ред декларира променлива от тип Parent, която се инициализира с препратка към обект, извлечен от ChildOfChild. Във втория ред операторът instanceof анализира съвместимостта на препратка от тип Parent с класа Child и включеният обект не е извлечен нито от първия, нито от втория клас. Операторът обаче ще върне true, тъй като класът, от който е извлечен този обект, наследява от Child.

Нека добавим още един клас:

Нека отново декларираме променлива от тип Parent:

Променливата p е от тип Parent, което означава, че може да препраща към обекти от тип Child или Child2. Операторът instanceof помага да се разбере ситуацията:

За нулева препратка операторът instanceof винаги ще връща false.

С изучаването на свойствата на обектния модел на Java ще се върнем към алгоритъма на оператора instanceof.

Операторите за сравнение == и != проверяват равенството (или неравенството) на стойностите на обекта чрез препратка. Въпреки това, често се изисква алтернативно сравнение по стойност. Сравнението по стойност се занимава с представата за състоянието на даден обект. Самото значение на този израз се разглежда в OOP, тъй като за изпълнението в Java състоянието на обекта се съхранява в неговите полета. При сравняване по препратка не се вземат предвид нито типът на обекта, нито стойностите на неговите полета, връща се true само ако и двете препраткисочат към същия обект.

Първото сравнение е вярно, защото p2 се отнася за същия обект като p1. Второто сравнение е невярно, въпреки факта, че променливата p3 се отнася до точков обект с точно същите координати. Това обаче е различен обект, който е създаден от различен нов израз.

Ако един от аргументите на оператора == е null, а другият не е, тогава стойността на такъв израз ще бъде false. Ако и двата операнда са нула, тогава резултатът ще бъде верен.

За правилно сравнение по стойност има специален метод равенства, който ще бъде обсъден по-късно. Например низовете могат да се сравняват по следния начин:

Условна операция? : работи както обикновено и може да приема втори и трети аргумент, ако и двата са референтни типове едновременно. Резултатът от такъв оператор също ще има тип обект.

Клас обект