CodeGym /Kurslar /JAVA 25 SELF /Parametrlərin dəyər üzrə və istinad üzrə ötürülməsi

Parametrlərin dəyər üzrə və istinad üzrə ötürülməsi

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Fərqli proqramlaşdırma dillərində funksiyalara (və ya metodlara) parametrləri ötürməyin iki əsas yolu var:

  • Dəyər üzrə: funksiya dəyişənin dəyərinin surətini alır. Funksiya parametri dəyişsə belə, orijinal dəyişmir.
  • İstinad üzrə: funksiya orijinal obyektə «istinad» (göstərici) alır. Funksiya içindəki dəyişikliklər orijinalda əks olunur.

Java-da BÜTÜN parametrlər dəyər üzrə ötürülür!
Amma incəlik var: primitiv tipləri (int, double, boolean və s.) ötürəndə, məhz dəyərin özü kopyalanır. İstinad tiplərini (məsələn, massivlər və obyektlər) ötürəndə isə istinadın dəyəri (yəni obyektin yaddaşdakı «ünvanı») kopyalanır, obyektin özü deyil.

Beyniniz «əriyir» kimi hiss edirsinizsə, narahat olmayın — indi hər şeyi addım‑addım izah edib nümunələrlə göstərəcəyik!

2. Primitiv tiplər: dəyər kopyalanır

Sadədən başlayaq: metodun içində int tipli dəyişənin dəyərini dəyişməyə çalışsaq nə baş verər?

public class Demo 
{
    public static void main(String[] args) 
    {
        int number = 5;
        changeValue(number);
        System.out.println(number); // Nə çap olunacaq?
    }

    public static void changeValue(int n) 
    {
        n = 42;
    }
}

Nəticə: ekrana 5 çıxacaq.

Niyə?
changeValue metoduna number dəyişəninin DƏYƏRİNİN SURƏTİ ötürülür. Metodun içində yalnız surəti (n) dəyişirik; main-dəki orijinal number toxunulmamış qalır.

Bənzətmə
Təsəvvür edin, dostunuza pasportunuzun surətini verirsiniz, orijinalını yox. Dostunuz surətin üzərində istədiyi kimi «bığ çəkə» bilər — amma sizin əsl pasportunuz əvvəlki kimi qalacaq!

3. İstinad tipləri: istinad kopyalanır

İndi eyni şeyi massivlə yoxlayaq:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] numbers = {1, 2, 3};
        changeFirst(numbers);
        System.out.println(numbers[0]); // Nə çap olunacaq?
    }

    public static void changeFirst(int[] arr) 
    {
        arr[0] = 99;
    }
}

Nəticə: ekrana 99 çıxacaq.

Niyə?
changeFirst metoduna numbers massivi üzərinə olan İSTİNADIN surəti ötürülür. Həm numbers main-də, həm də arr metodda yaddaşda eyni massivə işarə edir. Buna görə də, metoddakı massiv elementini dəyişsək, dəyişiklik «çöldən» də görünür.

Vizualizasiya

main: numbers ──► [1, 2, 3]
                   ▲
                   │
changeFirst: arr ──┘
İstinadın surəti yaddaşda eyni obyektə işarə edir

arr[0]-ı dəyişərək əslində numbers[0]-ı dəyişirik, çünki hər ikisi eyni obyektə işarə edir.

4. Amma istinadın özünü dəyişsəniz — ilkin obyekt dəyişməyəcək!

İndi belə edək:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] numbers = {1, 2, 3};
        replaceArray(numbers);
        System.out.println(numbers[0]); // Nə çap olunacaq?
    }

    public static void replaceArray(int[] arr) 
    {
        arr = new int[] {10, 20, 30};
    }
}

Nəticə: 1 çap olunacaq.

Niyə?
replaceArray metodunda arr dəyişəni yeni massivə işarə etməyə başlayır, lakin bu, main-dəki numbers dəyişəninə təsir etmir.
Onlar eyni istinada bağlı idilər, amma metod daxilində arr = ... təyin edəndə bu yalnız lokal dəyişiklik olur.

Bənzətmə
Bu elə bil sizdə də, dostunuzda da eyni mənzilin açarı var. Dostunuz özünə yeni açar düzəltdi, amma sizin köhnə açar yerində qaldı və qapı da əvvəlki kimidir.

5. Möhkəmləndirici nümunələr: iki int-i metoddan «yerini dəyişmək» mümkün deyil

Bir çox yeni başlayanlar iki ədədi yerlərini dəyişdirən metod yazmağa çalışır, amma alınmır:

public class Demo 
{
    public static void main(String[] args) 
    {
        int a = 5, b = 10;
        swap(a, b);
        System.out.println(a + " " + b); // Gözlənti: 10 5, bəs əslində?
    }

    public static void swap(int x, int y) 
    {
        int temp = x;
        x = y;
        y = temp;
    }
}

Nəticə: ekrana 5 10 çıxacaq.

Niyə?
Çünki swap-a ab dəyişənlərinin surətləri düşür. swap daxilində etdiklərimiz yalnız bu surətlərə təsir edir, orijinallara yox.

6. Amma massivlərdə məzmunu dəyişmək olar!

Massivdəki dəyərləri yerlərini düzgün şəkildə necə dəyişmək olar, baxaq:

public class Demo 
{
    public static void main(String[] args) 
    {
        int[] arr = {5, 10};
        swap(arr);
        System.out.println(arr[0] + " " + arr[1]); // Gözlənti: 10 5
    }

    public static void swap(int[] arr) 
    {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp;
    }
}

Nəticə: 10 5 çap olunacaq.

Niyə?
Çünki biz həm orijinal dəyişənin, həm də metod parametrinin işarə etdiyi obyektin (massivin) məzmununu dəyişirik.

7. Demonstrasiya: obyektlər və onların sahələri

Massivlərlə aydın oldu. Bəs öz siniflərimizin obyektləri necə? Tam olaraq eyni!

class Box 
{
    int value;
}

public class Demo
{
    public static void main(String[] args) 
    {
        Box box = new Box();
        box.value = 7;
        changeBox(box);
        System.out.println(box.value); // Nə çap olunacaq?
    }

    public static void changeBox(Box b) 
    {
        b.value = 42;
    }
}

Nəticə: 42 çap olunacaq.

Niyə?
Çünki istinadın işarə etdiyi obyektin sahəsini dəyişirik.

Parametrlər metodlara ötürüləndə nə baş verir

Nə ötürürük Necə kopyalanır Metod daxilində dəyişmək olar? Dəyişikliklər çöldən görünür?
int, double və s. Dəyərin surəti Bəli, amma yalnız surəti Xeyr
Massiv İstinadın surəti Bəli, elementləri dəyişsəniz Bəli
Obyekt (sinif) İstinadın surəti Bəli, sahələri dəyişsəniz Bəli
Massiv/obyekt İstinadın surəti Xeyr, yeni istinad təyin etsəniz Xeyr

8. Tipik səhvlər

Səhv № 1: metodu çağırandan sonra int-in dəyişəcəyini gözləmək. Bir çox yeni başlayanlar int tipli dəyişəni metoda verəndə, onun dəyərini metod daxilində dəyişməyin mümkün olduğunu düşünür. Bu yanlışdır: yalnız surət dəyişir!

Səhv № 2: iki int-i metodla yerini dəyişmək cəhdi. Artıq gördüyümüz kimi, bu mümkün deyil — yalnız dəyişənlərin surətləri yerini dəyişir, orijinallara toxunulmur.

Səhv № 3: massivi metoddan «əvəzləmək» cəhdi. Əgər metod daxilində parametr‑massivə yeni massiv təyin etsəniz (arr = new int[]{...}), bu orijinal massivə təsir etməyəcək. Massivi «əvəzləmək» üçün — metoddan yeni massivi qaytarıb onu çağıran tərəfdə dəyişənə təyin etmək lazımdır.

Səhv № 4: obyektin məzmununu dəyişməyin mümkün olduğunu unutmaq. Əgər obyekt (və ya massiv) ötürürsünüzsə — onun sahə/elementlərində etdiyiniz hər bir dəyişiklik çöldən görünəcək!

Səhv № 5: null ilə çaşqınlıq. Əgər metoda null-a bərabər istinad ötürsəniz və onun sahələrinə müraciət etməyə çalışsanız — NullPointerException alacaqsınız. Ehtiyatlı olun!

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Robotun trayektoriyasındakı başlanğıc nöqtəsinin sıfırlanması 🤖
Robotun trayektoriyasındakı başlanğıc nöqtəsinin sıfırlanması 🤖
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Oyunçu bonus siyahısını yeniləmək cəhdi 🎁
Oyunçu bonus siyahısını yeniləmək cəhdi 🎁
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Futbol komandasında oyunçuların yerlərinin dəyişdirilməsi ⚽
Futbol komandasında oyunçuların yerlərinin dəyişdirilməsi ⚽
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sehrli sandığın məzmununun yenilənməsi 📦
Sehrli sandığın məzmununun yenilənməsi 📦
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION