1. Xüsusiyyətlər: getter və setter
Böyük bir layihə eyni anda onlarla proqramçı tərəfindən hazırlanırsa, çox vaxt onların sinif sahələrində saxlanılan məlumatlara fərqli yanaşmaları ilə bağlı problemlər ortaya çıxır.
Heç kim siniflərə aid sənədləri ətraflı şəkildə öyrənmir və ya sənədlərdə bütün hallara aid məlumat verilməmiş ola bilər, buna görə də çox vaxt obyektin daxili məlumatlarının «xarab olması» və obyektin keçərsiz hala düşməsi ilə bağlı vəziyyətlər baş verir.
Bu cür vəziyyətlərin qarşısını almaq üçün, Java-da qəbul olunub ki, sinif sahələrinin hamısı private edilməlidir. Yalnız sinifin metodları sinifin dəyişənlərini dəyişə bilər və başqa siniflərin heç bir metodu sinif dəyişənlərinə birbaşa daxil ola bilməz. Budur.
Əgər istəyirsiniz ki, başqa siniflər sizin sinifdəki obyektlərin daxili məlumatlarını əldə edə və ya dəyişə bilsin, sinfinizin koduna iki metod əlavə etməlisiniz — get-metod və set-metod. Nümunə:
Kod | Qeyd |
---|---|
|
private -sahə nameSahənin konstruktor vasitəsilə inizializasiyası getName() — metod sahə name-in dəyərini geri qaytarırsetName() — metod sahə name-in dəyərini dəyişir |
Başqa heç bir sinif sahə name-in dəyərini birbaşa dəyişə bilməz. Kimsə sahə name-in dəyərini əldə etmək istəyirsə, getName()
metodunu Person
tipindəki obyektə müraciət etməlidir. Hər hansısa bir kod sahə name-in dəyərini dəyişmək istəyirsə, o, setName()
metodunu Person
tipindəki obyektə çağırmalıdır.
getName()
metodu bəzən sahə name-in «getter»-i adlanır, setName()
metodu isə sahə name-in «setter»-i.
Bu çox yayılmış bir yanaşmadır. Bütün Java kodunun 80-90%-ində heç vaxt sinifin publik dəyişənlərini görməyəcəksiniz. Onlar əvəzinə ya private
(ya da protected
) elan olunmuş olacaq və hər dəyişən üçün publik getter və setter olacaq.
Bu yanaşma kodu uzadır, amma onu daha etibarlı edir.
Sinif dəyişəninə birbaşa müraciət — bu «ikili xətti keçməklə dönmə»-yə bənzəyir: daha sadə və tezdir, amma əgər bunu hamı belə edərsə, bu hamıya zərər verəcək.
Tutaq ki, düz müstəvidə bir nöqtəni təsvir edən bir sinif yaratmaq istəyirsiniz x
və y
. Budur, bunu necə newbie bir proqramçı edərdi:
class Point
{
public int x;
public int y;
}
Bəs bunu təcrübəli Java proqramçısı necə edərdi:
Kod |
---|
|
Kod uzandı? Əlbəttə.
Ancaq set və get metodlarına parametrlərin validasiyasını əlavə edə bilərsiniz. Məsələn, x
və y
-nin həmişə sıfırdan böyük (və ya sıfırdan kiçik olmamaq şərtini) təmin edə bilərsiniz. Nümunə:
Kod | Qeyd |
---|---|
|
2. Obyektin yaşam müddəti
Artıq bilirsiniz ki, obyektlər new
operatoru ilə yaradılır, bəs obyektlər necə silinir? Axı onlar əbədi mövcud deyillər – yaddaş heç vaxt bu üçün kifayət etməz.
Çox proqramlaşdırma dillərində, məsələn, C++, obyektin silinməsi üçün xüsusi delete
operatoru var. Bəs Java-da vəziyyət necədir?
Java-da hər şey bir az fərqlidir və Java-da delete
operatoru yoxdur. Bu obyektlərin Java-da silinməməsi deməkdirmi? Əlbəttə ki, yox. Yoxsa Java tətbiqlərində yaddaş tez bir zamanda tükənərdi və bir neçə aylıq fasiləsiz işdən danışmaq mümkün olmazdı.
Java-da obyektlərin silinməsi prosesi tam avtomatlaşdırılıb – obyektlərin silinməsi Java-maşının tərəfindən həyata keçirilir. Belə proses garbage collecting (zibilin toplanması) adlanır, zibili toplayan mexanizm isə Garbage Collector və ya qısaca GC adlanır.
Bəs Java maşını necə biləcək ki, hansı obyektin silinməsi lazımdır və nə vaxt?
Bütün obyektlər zibili toplayan tərəfindən çatdırılan və ya çatdırıla bilməyən olaraq bölünür. Əgər obyektə heç olmasa bir istinad varsa, o çatdırılır hesab olunur. Əgər obyektə istinad edən heç bir dəyişən yoxdursa, o obyekt çatdırıla bilməyən hesab olunur və zibil olaraq elan edilir: deməli, onu silmək olar.
Java-da mövcud obyektə sadəcə keçid etmək mümkün deyil: yalnız onu təyin etmək olar. Əgər obyektə olan bütün keçidləri sildiksə, o həmişəlik itir.
Dairəvi keçidlər
Əvvəlki məntiq əla səslənir, ancaq sadə bir əks nümunə tapana qədər: iki obyektimiz var ki, onlar bir-birinə keçid edir (bir-birilərinə keçidlərini saxlayırlar). Başqa heç kim bu obyektlərə keçid saxlamır.
Bu obyektlərə qalan kodlardan müraciət etmək mümkün deyil, lakin hələ də onlara keçid var.
Məhz buna görə zibili toplayan obyektləri "keçidləri olan obyektlər" və "keçidləri olmayan obyektlər" olaraq deyil, çatdırılan və çatdırıla bilməyən olaraq bölür.
Çatdırılan obyektlər
Əvvəlcə 100% canlı olan obyektlər çatdırılan siyahısına əlavə edilir. Məsələn, cari axın (Thread.current()
) və ya Konsol (System.in
).
Daha sonra birinci çatdırılan obyektlərə keçid edən obyektlər çatdırılan siyahısına əlavə edilir. Daha sonra birincilərinə keçid edən ikincilər, s. davam edir.
Beləliklə, öz aralarında keçid edən müəyyən obyekt qrupları varsa, lakin çatdırılan obyektlərdən onlara keçid etmək mümkün deyilsə, belə obyektlər zibil hesab olunur və silinir.
3. Zibil yığımı
Yaddaşın fraqmentləşməsi
Obyektlərin silinməsi ilə bağlı başqa bir vacib məqam — yaddaşın fraqmentləşməsi. Əgər obyektləri davamlı olaraq yaradıb silsək, tez bir zamanda yaddaş qarışıq olacaq: tutulmuş yaddaş sahələri boş sahələrlə qarışacaq.
Və elə bir vəziyyət yarana bilər ki, böyük bir obyekt (məsələn, milyon elementlik massiv) yaratmaq mümkün olmayacaq, çünki böyük bir boş yaddaş parçası mövcud deyil. Yəni, boş yaddaş var, hətta çoxdur, amma böyük, bütöv bir yaddaş parçası ola bilməz.
Yaddaşın optimallaşdırılması (defraqmentasiya)
Java-maşını bu problemi spesifik bir şəkildə həll edir. Təxminən bu cür görünür:
Yaddaş iki hissəyə bölünür. Bütün obyektlər yalnız onun bir hissəsində yaradılır (və silinir). Yaddaşdakı boşluqları aradan qaldırma vaxtı gələndə, birinci hissədən olan bütün obyektlər ikinci hissəyə köçürülür. Amma obyektlər artıq bir-birinə sıx şəkildə köçürülür ki, boşluqlar olmasın.
Bu proses təxminən belə görünür:
Mərhələ 1: Obyektlər yaradıldıqdan sonra
Mərhələ 2: “Boşluqların” yaranması
Mərhələ 3: “Boşluqların” aradan qaldırılması
Bu şəkildə, obyektləri silməyə belə ehtiyac yoxdur. Java-maşını sadəcə bütün çatımlı obyektləri yeni bir yerə köçürür və köhnə obyektlərin olduğu yaddaş sahəsini tamamilə boş elan edir.
GO TO FULL VERSION