JavaRush /Java Blogu /Random-AZ /Java-da Təyinat və Başlama
Viacheslav
Səviyyə

Java-da Təyinat və Başlama

Qrupda dərc edilmişdir

Giriş

Kompüter proqramlarının əsas məqsədi məlumatların işlənməsidir. Məlumatı emal etmək üçün onu bir şəkildə saxlamaq lazımdır. Mən məlumatların necə saxlandığını başa düşməyi təklif edirəm.
Java-da Təyinat və İnisiallaşdırma - 1

Dəyişənlər

Dəyişənlər istənilən məlumatı saxlayan konteynerlərdir. Gəlin Oracle-dan rəsmi Təlimata baxaq: Üzv Dəyişənlərinin Elan edilməsi . Bu Təlimata uyğun olaraq, dəyişənlərin bir neçə növü var:
  • Sahələr : sinifdə elan edilmiş dəyişənlər;
  • Yerli dəyişənlər : metod və ya kod blokunda dəyişənlər;
  • Parametrlər : metod bəyannaməsində dəyişənlər (imzada).
Bütün dəyişənlərin dəyişən növü və dəyişən adı olmalıdır.
  • Dəyişənin növü dəyişənin hansı məlumatları təmsil etdiyini (yəni hansı məlumatları saxlaya biləcəyini) göstərir. Bildiyimiz kimi, dəyişənin növü primitiv (ibtidai olmayan ) deyil, primitiv (primitivlər) və ya obyekt ola bilər. Obyekt dəyişənləri ilə onların növü müəyyən bir sinif tərəfindən təsvir edilir.
  • Dəyişən adı kiçik hərflə, dəvə hərfində olmalıdır. Adlandırma haqqında ətraflı məlumatı " Dəyişənlər:Adlandırma " bölməsində oxuya bilərsiniz .
Həmçinin, əgər sinif səviyyəsində dəyişən, yəni. sinif sahəsidir, onun üçün giriş dəyişdiricisi təyin edilə bilər. Ətraflı məlumat üçün Sinif Üzvlərinə Girişə Nəzarət Baxın .

Dəyişən Bəyannaməsi

Beləliklə, dəyişənin nə olduğunu xatırlayırıq. Dəyişənlə işləməyə başlamaq üçün onu elan etməlisiniz. Əvvəlcə yerli dəyişənə baxaq. IDE əvəzinə, rahatlıq üçün biz tutorialspoint-dən onlayn həlldən istifadə edəcəyik: Onlayn IDE . Bu sadə proqramı onların onlayn IDE-də işlədək:

public class HelloWorld{
    public static void main(String []args){
        int number;
        System.out.println(number);
    }
}
Beləliklə, gördüyünüz kimi, biz name numbervə type ilə lokal dəyişən elan etdik int. "İcra et" düyməsini sıxırıq və səhv alırıq:

HelloWorld.java:5: error: variable number might not have been initialized
        System.out.println(number);
Nə olub? Biz dəyişən elan etdik, lakin onun dəyərini işə salmadıq. Qeyd etmək lazımdır ki, bu səhv icra zamanı deyil (yəni Runtime-da deyil), kompilyasiya zamanı baş verdi. Ağıllı kompilyator yerli dəyişənin ona daxil olmamışdan əvvəl işə salınıb-inisiallaşdırılmayacağını yoxladı. Beləliklə, aşağıdakı ifadələr bundan irəli gəlir:
  • Yerli dəyişənlərə yalnız işə salındıqdan sonra daxil olmaq lazımdır;
  • Yerli dəyişənlərin standart dəyərləri yoxdur;
  • Yerli dəyişənlərin dəyərləri tərtib zamanı yoxlanılır.
Beləliklə, bizə deyirlər ki, dəyişən işə salınmalıdır. Dəyişənin işə salınması dəyişənə dəyər təyin etməkdir. Gəlin bunun nə olduğunu və niyə olduğunu anlayaq.

Yerli dəyişənin işə salınması

Dəyişənlərin işə salınması Java-da ən çətin mövzulardan biridir, çünki... yaddaşla işləmək, JVM tətbiqi, JVM spesifikasiyası və digər eyni dərəcədə qorxulu və çətin şeylərlə çox sıx bağlıdır. Ancaq bunu ən azı müəyyən dərəcədə anlamağa cəhd edə bilərsiniz. Sadədən mürəkkəbə keçək. Dəyişənləri işə salmaq üçün təyinat operatorundan istifadə edəcəyik və əvvəlki kodumuzdakı xətti dəyişəcəyik:

int number = 2;
Bu seçimdə heç bir səhv olmayacaq və dəyər ekranda görünəcək. Bu halda nə baş verir? Gəlin əsaslandırmağa çalışaq. Əgər biz dəyişənə dəyər təyin etmək istəyiriksə, o zaman həmin dəyişənin dəyəri saxlamasını istəyirik. Belə çıxır ki, dəyəri hardasa saxlamaq lazımdır, bəs harada? Diskdə? Amma bu, çox ləng gedir və bizə məhdudiyyətlər qoya bilər. Məlum oldu ki, məlumatları "burada və indi" tez və səmərəli saxlaya biləcəyimiz yeganə yer yaddaşdır. Bu o deməkdir ki, yaddaşda bir az yer ayırmalıyıq. Bu doğrudur. Dəyişən işə salındıqda, proqramımızın icra olunacağı java prosesinə ayrılmış yaddaşda onun üçün yer ayrılacaq. Java prosesinə ayrılan yaddaş bir neçə sahəyə və ya zonaya bölünür. Onlardan hansının yer ayıracağı dəyişənin hansı tip elan olunduğundan asılıdır. Yaddaş aşağıdakı bölmələrə bölünür: Heap, Stack və Non-Heap . Stek yaddaşından başlayaq. Stack yığın kimi tərcümə olunur (məsələn, kitab yığını). Bu, LIFO (Son gələn, ilk çıxan) məlumat strukturudur. Yəni kitab yığını kimi. Biz ona kitablar əlavə etdikdə onları üstünə qoyuruq, götürdükdə isə yuxarısını (yəni ən son əlavə olunanı) götürürük. Beləliklə, proqramımızı işə salırıq. Bildiyimiz kimi, Java proqramı JVM, yəni Java virtual maşını tərəfindən icra edilir. JVM proqramın icrasının harada başlamalı olduğunu bilməlidir. Bunun üçün “giriş nöqtəsi” adlanan əsas metodu elan edirik. JVM-də icra üçün əsas ip (Mövzu) yaradılır. Bir ip yaradıldıqda, onun yaddaşda öz yığını ayrılır. Bu yığın çərçivələrdən ibarətdir. Hər bir yeni metod bir mövzuda icra edildikdə, onun üçün yeni bir çərçivə ayrılacaq və yığının yuxarı hissəsinə əlavə olunacaq (kitab yığınındakı yeni kitab kimi). Bu çərçivədə obyektlərə və primitiv tiplərə istinadlar olacaq. Bəli, bəli, intimiz stekdə saxlanacaq, çünki... int primitiv tipdir. Çərçivə ayırmadan əvvəl JVM orada nəyi saxlamalı olduğunu başa düşməlidir. Məhz bu səbəbdən “dəyişən işə salınmamış ola bilər” xətası alacağıq, çünki işə salınmazsa, JVM bizim üçün yığın hazırlaya bilməyəcək. Buna görə də, proqramı tərtib edərkən, ağıllı kompilyator bizə səhv etməkdən və hər şeyi pozmaqdan qaçmağa kömək edəcəkdir. (!) Aydınlıq üçün mən super bir məqaləni tövsiyə edirəm: “ Java Stack and Heap: Java Memory Allocation Tutorial ”. O, eyni dərəcədə sərin videoya keçid verir:
Metodun icrası başa çatdıqdan sonra bu üsullar üçün ayrılmış çərçivələr ipin yığınından silinəcək və onlarla birlikdə bütün verilənlərlə birlikdə bu kadr üçün ayrılmış yaddaş təmizlənəcək.

Yerli Obyekt Dəyişənlərinin Başlanması

Gəlin kodumuzu yenidən bir az daha çətinə dəyişdirək:

public class HelloWorld{

    private int number = 2;
    
    public static void main(String []args){
        HelloWorld object = new HelloWorld();
        System.out.println(object.number);
    }
    
}
Burada nə olacaq? Gəlin bu barədə bir daha danışaq. JVM proqramı haradan icra etməli olduğunu bilir, yəni. əsas üsulu görür. O, bir ip yaradır və onun üçün yaddaş ayırır (hər şeydən sonra ipin icra üçün lazım olan məlumatları haradasa saxlaması lazımdır). Bu mövzuda əsas metod üçün çərçivə ayrılmışdır. Sonra HelloWorld obyekti yaradırıq. Bu obyekt artıq yığında deyil, yığında yaradılır. Çünki obyekt primitiv tip deyil, obyekt tipidir. Və yığın yalnız yığındakı obyektə istinadı saxlayacaq (biz bu obyektə birtəhər daxil olmalıyıq). Sonra, əsas metodun yığınında println metodunun icrası üçün çərçivələr ayrılacaq. Əsas metodu yerinə yetirdikdən sonra bütün çərçivələr məhv ediləcək. Çərçivə məhv edilərsə, bütün məlumatlar məhv ediləcək. Obyekt obyekti dərhal məhv edilməyəcək. Birincisi, ona istinad məhv ediləcək və beləliklə, daha heç kim obyekt obyektinə istinad etməyəcək və yaddaşda bu obyektə giriş artıq mümkün olmayacaq. Ağıllı JVM-nin bunun üçün öz mexanizmi var - zibil yığan (zibil yığan və ya qısaca GC). Daha sonra heç kimin istinad etmədiyi obyektləri yaddaşdan çıxarır. Bu proses yuxarıda verilmiş linkdə yenidən təsvir edilmişdir. Hətta izahatlı video da var.

Sahələr işə salınır

Sinifdə göstərilən sahələrin işə salınması sahənin statik olub-olmamasından asılı olaraq xüsusi şəkildə baş verir. Əgər sahədə static açar sözü varsa, onda bu sahə sinfin özünə aiddir və əgər static sözü göstərilməyibsə, onda bu sahə sinfin nümunəsinə istinad edir. Buna bir misalla baxaq:

public class HelloWorld{
    private int number;
    private static int count;
    
    public static void main(String []args){
        HelloWorld object = new HelloWorld();
        System.out.println(object.number);
    }
}
Bu nümunədə sahələr müxtəlif vaxtlarda işə salınır. Nömrə sahəsi HelloWorld sinif obyekti yaradıldıqdan sonra işə salınacaq. Lakin sinif Java virtual maşını tərəfindən yükləndikdə sayma sahəsi işə salınacaq. Sinif yüklənməsi ayrı bir mövzudur, ona görə də onu burada qarışdırmayacağıq. Sadəcə olaraq bilmək lazımdır ki, statik dəyişənlər sinif işləmə müddətində məlum olduqda işə salınır. Burada başqa bir şey daha vacibdir və siz bunu artıq hiss etdiniz. Biz heç bir yerdə dəyəri qeyd etmədik, amma işləyir. Və həqiqətən. Sahələr olan dəyişənlər, əgər onların müəyyən edilmiş dəyəri yoxdursa, onlar standart dəyərlə işə salınır. Rəqəmsal dəyərlər üçün bu, üzən nöqtəli nömrələr üçün 0 və ya 0.0-dır. Boolean üçün bu yanlışdır. Və bütün obyekt tipli dəyişənlər üçün dəyər sıfır olacaq (bu barədə daha sonra danışacağıq). Deyəsən, bu niyə belədir? Lakin obyektlər Heap-də (yığında) yaradıldığı üçün. Bu sahə ilə iş Runtime proqramında həyata keçirilir. Və biz bu dəyişənləri icra müddətində işə sala bilərik, yaddaşı icradan əvvəl hazırlanmalı olan yığından fərqli olaraq. Java-da yaddaş belə işləyir. Ancaq burada daha bir xüsusiyyət var. Bu kiçik parça yaddaşın müxtəlif guşələrinə toxunur. Xatırladığımız kimi, əsas metod üçün Stack yaddaşında çərçivə ayrılmışdır. Bu çərçivə yığın yaddaşında obyektə istinadı saxlayır. Bəs onda sayma harada saxlanılır? Xatırladığımız kimi, bu dəyişən obyekt yığında yaradılmazdan əvvəl dərhal işə salınır. Bu, həqiqətən çətin sualdır. Java 8-dən əvvəl PERMGEN adlı yaddaş sahəsi var idi. Java 8-dən başlayaraq bu sahə dəyişdi və METASPACE adlanır. Əslində, statik dəyişənlər sinif tərifinin bir hissəsidir, yəni. onun metadatası. Buna görə də, onun metadata deposunda, METASPACE-də saxlanması məntiqlidir. MetaSpace eyni Qeyri-Heap yaddaş sahəsinə aiddir və onun bir hissəsidir. Dəyişənlərin elan olunma ardıcıllığının nəzərə alındığını da nəzərə almaq lazımdır. Məsələn, bu kodda bir səhv var:

public class HelloWorld{
    
    private static int b = a;
    private static int a = 1;
    
    public static void main(String []args){
        System.out.println(b);
    }
    
}

Null nədir

Yuxarıda qeyd edildiyi kimi, obyekt tiplərinin dəyişənləri, əgər onlar bir sinfin sahələridirsə, defolt dəyərlərə işə salınır və bu standart dəyər sıfırdır. Bəs Java-da null nədir? Xatırlamaq lazım olan ilk şey odur ki, primitiv tiplər sıfır ola bilməz. Və hamısı ona görə ki, null heç bir yerə, heç bir obyektə istinad etməyən xüsusi istinaddır. Buna görə də yalnız obyekt dəyişəni null ola bilər. Anlamaq üçün vacib olan ikinci şey, null-un istinad olmasıdır. Mən də onların çəkilərinə istinad edirəm. Bu mövzuda stackoverflow haqqında sualı oxuya bilərsiniz: " Null dəyişəni yaddaşda yer tələb edirmi ".

Başlanğıc blokları

Dəyişənlərin inisializasiyasını nəzərdən keçirərkən, başlanğıc bloklarını nəzərə almamaq günah olardı. Bu belə görünür:

public class HelloWorld{
    
    static {
        System.out.println("static block");
    }
    
    {
        System.out.println("block");
    }
    
    public HelloWorld () {
        System.out.println("Constructor");
    }
    
    public static void main(String []args){
        HelloWorld obj = new HelloWorld();
    }
    
}
Çıxış sırası belə olacaq: statik blok, blok, Konstruktor. Gördüyümüz kimi inisializasiya blokları konstruktordan əvvəl yerinə yetirilir. Və bəzən bu, işə salmaq üçün əlverişli bir vasitə ola bilər.

Nəticə

Ümid edirəm ki, bu qısa icmal onun necə işlədiyinə və nə üçün olduğuna dair bir az fikir verə bildi. #Viaçeslav
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION