CodeGym /Kurslar /JAVA 25 SELF /Statik yuvalanmış siniflər (static nested)

Statik yuvalanmış siniflər (static nested)

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

1. Statik yuvalanmış sinif

Statik yuvalanmış sinif (static nested class) — başqa bir sinifin daxilində modifikatorla static elan edilən sinifdir. Mahiyyətcə bu, başqa bir sinifin içində “yaşayan”, lakin onun obyekti ilə bağlı olmayan adi sinifdir.

Əgər daxili sinif böyük qardaşının (xarici sinif obyektinin) əlini daim buraxmayan kiçik qardaşa bənzəyirsə, statik yuvalanmış sinif isə yalnız ailə bayramlarına gələn, qalan vaxt öz həyatı olan əmioğludur.

Açar fərqlər:

  • Xarici sinif obyektinə örtülü istinad etmir — heç bir OuterClass.this və qeyri‑statik üzvlərə giriş yoxdur.
  • Statik üzvlər saxlaya bilər (adi daxili sinifdən fərqli olaraq).
  • Xarici sinifin obyekti olmadan yaradılır.

Elan sintaksisi

Statik yuvalanmış sinfi elan etmək çox asandır: xarici sinifin içində static açar sözündən istifadə edirik.

class Outer {
    static class Nested {
        void print() {
            System.out.println("Hello from Nested!");
        }
    }
}

Vəssalam! Heç bir hiyləli sintaktik konstruksiya — sadəcə static class.

Vizualizasiya:

Outer (xarici sinif)
│
├── Nested (static nested class)
│      └── print()

2. Statik yuvalanmış sinifin nümunəsinin yaradılması

Ən xoşu: xarici sinifin obyektinə ehtiyac yoxdur!

Outer.Nested nested = new Outer.Nested();
nested.print(); // Hello from Nested!

Diqqət edin: biz sinifin tam adından — Outer.Nested — istifadə edirik. Bu, yuvalanmış sinfə soyad vasitəsilə müraciət etməyə bənzəyir: “Smith.Son”.

Daxili (inner) siniflə müqayisə edin:

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // outer obyektinə ehtiyac var

Static nested üçün isə ümumiyyətlə Outer obyektinə ehtiyac yoxdur!

3. Xarici sinifin üzvlərinə giriş

Məhz burada daxili sinifdən əsas fərq özünü göstərir.

  • Statik yuvalanmış sinif YALNIZ xarici sinifin statik üzvlərinə girişə malikdir.
  • Qeyri‑statik sahə və metodlara müraciət etmək olmaz (hətta onlar public olsa belə).

Nümunə:

class Outer {
    private static int staticValue = 10;
    private int instanceValue = 20;

    static class Nested {
        void show() {
            System.out.println("Static value: " + staticValue); // OK
            // System.out.println("Instance value: " + instanceValue); // Səhv!
        }
    }
}

Əgər instanceValue kimi qeyri‑statik sahəyə müraciət etməyə çalışsanız, kompilyator dərhal etiraz edəcək.

Niyə belədir? Çünki static nested class hansı Outer obyekti ilə əlaqələndiriləcəyini “bilmir” — onun xarici sinif obyektinə istinadı yoxdur.

4. Statik yuvalanmış siniflərdən nə vaxt istifadə etməli

Onlar nə vaxt münasibdir?

  • Yuvalanmış sinif məntiqi olaraq xarici siniflə əlaqəlidir, lakin xarici sinif obyektinə giriş tələb etmir.
  • Köməkçi strukturu kapsullaşdırmaq istədikdə: məsələn, builder, utilit, enum və ya kiçik dəyişməz (immutable) obyekt.
  • Paketin “çirklənməsini” azaltmaq lazım olduqda: sinif yalnız xarici sinifə lazımdırsa, onu kənara çıxarmağa ehtiyac yoxdur.

Tipik ssenarilər:

  • Builder nümunəsi (xüsusən də dəyişməz obyektlər üçün)
  • Köməkçi strukturların reallaşdırılması: məsələn, kolleksiyalarda daxili Node sinifləri
  • Konstantların qruplaşdırılması və ya utilitlər

Sadə seçim qaydası
Özünüzə sual verin: “Yuvalanmış sinifimə xarici sinifin konkret obyektinə giriş lazımdırmı?”
YOX → static class (statik yuvalanmış) istifadə edin
BƏLİ → adi class (daxili/inner) istifadə edin

5. İstifadə nümunələri

Nümunə 1: Sinif üçün Builder

Tutaq ki, bizdə Person sinfi var və onun üçün Builder nümunəsini həyata keçirmək istəyirik:

public class Person {
    private final String name;
    private final int age;

    // Özəl konstruktor
    private Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    // Builder üçün statik yuvalanmış sinif
    public static class Builder {
        private String name;
        private int age;

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAge(int age) {
            this.age = age;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }

    public void printInfo() {
        System.out.println("Person: " + name + ", " + age);
    }
}

İstifadə:

Person person = new Person.Builder()
    .setName("Ivan")
    .setAge(30)
    .build();

person.printInfo(); // Person: Ivan, 30

Niyə Builder — statik yuvalanmış sinifdir?
Çünki o, Person obyektindən asılı deyil, sadəcə onu yaratmağa kömək edir. O, məntiqi olaraq Person ilə əlaqəlidir, lakin konkret nümunə ilə yox.

Nümunə 2: Kolleksiya daxilində köməkçi struktur

Təsəvvür edək ki, “rəqəmlərdən qutu” sinfi var və elementlərin saxlanması üçün daxili statik Node sinfindən istifadə olunur:

public class IntBox {
    private Node head;

    // Yuvalanmış static class
    private static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public void add(int value) {
        Node node = new Node(value);
        node.next = head;
        head = node;
    }

    public void printAll() {
        Node current = head;
        while (current != null) {
            System.out.println(current.value);
            current = current.next;
        }
    }
}

İstifadə:

IntBox box = new IntBox();
box.add(1);
box.add(2);
box.add(3);
box.printAll(); // 3 2 1

Niyə Node — static-dir?
Çünki hər bir Node bütün qutu (IntBox) barədə “bil­mə­mə­li­dir”; o, sadəcə məlumatı və növbəti Node-a keçidi saxlayır.

Nümunə 3: Əsas sinif daxilində utilit sinif

public class MathUtils {
    // Mürəkkəb ədədlərlə işləmək üçün statik yuvalanmış sinif
    public static class Complex {
        private final double re;
        private final double im;

        public Complex(double re, double im) {
            this.re = re;
            this.im = im;
        }

        public Complex add(Complex other) {
            return new Complex(this.re + other.re, this.im + other.im);
        }

        @Override
        public String toString() {
            return re + " + " + im + "i";
        }
    }
}

İstifadə:

MathUtils.Complex a = new MathUtils.Complex(1, 2);
MathUtils.Complex b = new MathUtils.Complex(3, 4);
MathUtils.Complex sum = a.add(b);
System.out.println(sum); // 4.0 + 6.0i

6. Faydalı nüanslar

Daxili sinif vs statik yuvalanmış sinif

Daxili (inner) sinif Statik yuvalanmış (static nested)
Açar söz yoxdur
static
Xarici obyektə örtülü istinad bəli yox
Xarici sinifin qeyri-statik üzvlərinə giriş bəli yox
Xarici sinifin statik üzvlərinə giriş bəli bəli
Statik üzvlər saxlaya bilər yoxdur (yalnız sabitlər) bəli
Yaradılma sintaksisi
outer.new Inner()
new Outer.Nested()
İstifadə Xarici sinifin obyektinə giriş lazım olduqda Xarici sinifin obyektinə giriş lazım olmadıqda

İllustrasiya

flowchart LR
    OuterClass -->|has| InnerClass
    OuterClass -.->|has| StaticNestedClass
    StaticNestedClass -.->|can access| staticMembers
    InnerClass -->|can access| instanceMembers
    InnerClass -->|can access| staticMembers

Xüsusiyyətlər və məhdudiyyətlər

  • Static nested class həm adi, həm də statik sahə və metodlara malik ola bilər.
  • İstənilən giriş modifikatoru ilə elan oluna bilər (public, private, protected, package-private).
  • Interfeysləri reallaşdıra və digər siniflərdən miras ala bilər.
  • Generic ola bilər.
  • Adətən, xarici sinifdən kənarda lazım olmayan xidmət siniflərini kapsullaşdırmaq üçün istifadə olunur.

Generic static nested class nümunəsi:

public class Box {
    public static class Holder<T> {
        private T value;
        public Holder(T value) { this.value = value; }
        public T get() { return value; }
    }
}

Static nested class-dan nə zaman istifadə ETMƏMƏK lazımdır

  • Əgər yuvalanmış sinfə xarici sinifin qeyri‑statik sahə/metodlarına giriş lazımdırsa — adi inner class istifadə edin.
  • Əgər sinif xarici sinifdən kənarda da lazımdırsa — onu ayrıca fayla çıxarın.
  • Əgər sinif həddindən artıq böyük və ya mürəkkəbdirsə — onu ayrı etmək daha yaxşıdır.

7. Tipik səhvlər və nüanslar

Səhv № 1: inner və static nested sinifin qarışdırılması.
Bir çox yeni başlayanlar static nested class daxilində xarici sinifin qeyri‑statik sahələrinə müraciət etməyə çalışırlar. Lakin static nested class xarici sinif obyektinə istinada malik deyil, buna görə bu mümkün deyil. Konkret obyektin vəziyyətinə girmək lazımdırsa — adi inner class istifadə edin.

Səhv № 2: static nested class-ı xarici sinifin obyekti vasitəsilə yaratmağa cəhd.
outer.new Inner() yazmağa ehtiyac yoxdur. Static nested class üçün həmişə new Outer.Nested() istifadə edin.

Səhv № 3: xarici sinifin nümunəsinə giriş tələb edən məntiq üçün static nested class istifadə etmək.
Əgər sinifin məntiqi xarici sinif obyektinin vəziyyəti ilə sıx bağlıdırsa, static nested class pis seçimdir. Adi daxili sinifdən istifadə edin.

Səhv № 4: Həddindən artıq dərin yuvalanma.
Yuvalanmış siniflərdən sui‑istifadə etməyin. Struktur dolaşıq hala gəlirsə, bəzi sinifləri bayıra çıxarmaq daha yaxşıdır.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sehrbazın alət dəsti: sehrin aktivləşdirilməsi 🔮
Sehrbazın alət dəsti: sehrin aktivləşdirilməsi 🔮
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Gizli anbar: giriş səviyyəsi 🛡️
Gizli anbar: giriş səviyyəsi 🛡️
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Dəyərli əşyaların uçotu: artefakt zənciri 💎
Dəyərli əşyaların uçotu: artefakt zənciri 💎
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Nəşriyyat evi: yeni kitabın yaradılması 📚
Nəşriyyat evi: yeni kitabın yaradılması 📚
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION