CodeGym /Kurslar /JAVA 25 SELF /switch-də pattern matching (Java 17/21+)

switch-də pattern matching (Java 17/21+)

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

1. Klassik switch: keçmişin məhdudiyyətləri

Gəlin, pattern matching ortaya çıxmamışdan əvvəl Java-da switch necə idi, xatırlayaq. Açıq danışsaq, xeyli konservativ idi. Yalnız primitivlərlə (int, char və bir az sonra enum, String) işləyirdi, əgər müxtəlif obyekt tiplərini işləmək istəyirdinizsə — uzun if-else zəncirləri yazmalı olurdunuz.

Object obj = ...;
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println("Sətir: " + s);
} else if (obj instanceof Integer) {
    Integer i = (Integer) obj;
    System.out.println("Ədəd: " + i);
} else if (obj == null) {
    System.out.println("null!");
} else {
    System.out.println("Başqa bir şey");
}

Rahatdır? O qədər də yox. Kod həcmli olur, asanlıqla səhv etmək olar və yeni tip əlavə olunsa — yenidən if-else zəncirini yenidən yazmaq lazım gəlir.

2. switch-də pattern matching: Java 17/21+-da inqilab

Java 17 (preview) və nəhayət Java 21+ pattern matching-i dəstəkləyən yeni switch versiyasını təqdim etdi. İndi switch təkcə primitivlərlə deyil, istənilən obyektlərlə, tiplərlə, hətta null ilə də işləyə bilir və əlavə şərtləri (guard-ifadələri) dəstəkləyir.

Yeni sintaksis: yığcamlıq və güc

switch-də sadə pattern matching nümunəsi:

Object obj = ...;
switch (obj) {
    case String s -> System.out.println("Sətir: " + s);
    case Integer i -> System.out.println("Ədəd: " + i);
    case null -> System.out.println("null!");
    default -> System.out.println("Başqa bir şey");
}

Burada nə baş verir?

  • Əgər obj — sətirdirsə, s dəyişəni avtomatik olaraq String tipinə gətirilir.
  • Əgər obj — tam ədəddirsə, i dəyişəni Integer olur.
  • Əgər obj — null-dırsa, xüsusi budaq işləyəcək.
  • Qalan hər şey — default.

Niyə bu rahatdır?

  • Əl ilə tip çevirmə yoxdur: Java tip təhlükəsizliyinə özü nəzarət edir.
  • Daha az kod: Artıq mötərizələr, kastlar və təkrarlamalar yoxdur.
  • Daha təhlükəsizdir: Kompilyator mümkün variantları unutmadığınızdan əmin olur (xüsusilə sealed-siniflərlə, bu barədə sonra danışacağıq).
  • Yeni tiplər əlavə etmək asandır: Sadəcə əlavə bir case budağı əlavə edin.

3. switch-də pattern matching: baza nümunələri

Nümunə 1: Müxtəlif tiplərin işlənməsi

Object obj = 42;

switch (obj) {
    case String s -> System.out.println("Sətir: " + s);
    case Integer i -> System.out.println("Ədəd: " + i);
    case null -> System.out.println("Bu null");
    default -> System.out.println("Naməlum tip");
}

Çıxış:

Ədəd: 42

Nümunə 2: Guard-ifadələrdən (when) istifadə

Bəzən təkcə tipi bilmək kifayət etmir — əlavə şərt də əlavə etmək istəyirsiniz.

Object obj = "Hello, world!";

switch (obj) {
    case String s when s.length() > 10 -> System.out.println("Uzun sətir: " + s);
    case String s -> System.out.println("Qısa sətir: " + s);
    case Integer i when i > 0 -> System.out.println("Müsbət ədəd: " + i);
    case Integer i -> System.out.println("Qeyri-müsbət ədəd: " + i);
    default -> System.out.println("Başqa bir şey");
}

Çıxış:

Uzun sətir: Hello, world!

Nəzərə alın:

  • when — bu, case üçün əlavə yoxlama olan guard-ifadədir.
  • Əgər şərt ödənmirsə, növbəti case-lər yoxlanılır.

Nümunə 3: null-un işlənməsi

Object obj = null;

switch (obj) {
    case null -> System.out.println("Bu null!");
    default -> System.out.println("Null deyil");
}

Çıxış:

Bu null!

4. Klasslar və irsiyyət ilə switch-də pattern matching

Pattern matching switch ilə sinif ierarxiyalarında xüsusilə yaxşı işləyir.

sealed interface Shape permits Circle, Rectangle, Square {}

final class Circle implements Shape {
    final double radius;
    Circle(double radius) { this.radius = radius; }
}

final class Rectangle implements Shape {
    final double width, height;
    Rectangle(double width, double height) { this.width = width; this.height = height; }
}

final class Square implements Shape {
    final double side;
    Square(double side) { this.side = side; }
}
Shape shape = new Rectangle(2, 3);

String description = switch (shape) {
    case Circle c -> "Radiusu " + c.radius + " olan dairə";
    case Rectangle r -> "Düzbucaqlı " + r.width + "x" + r.height;
    case Square s -> "Tərəfi " + s.side + " olan kvadrat";
};
System.out.println(description);

Çıxış:

Düzbucaqlı 2.0x3.0

Faydalı xüsusiyyət: Əgər siz sealed-siniflərdən istifadə edirsinizsə və onların bütün variantlarını işləyirsinizsə, default budağı tələb olunmur — kompilyator başa düşür ki, başqa variantlar ola bilməz!

5. record-siniflər və iç-içə patternlərlə switch-dən istifadə

switch-də pattern matching record-siniflərlə və iç-içə patternlərlə işləməyi dəstəkləyir (Java 21+-dən başlayaraq).

record Point(int x, int y) {}
record Line(Point start, Point end) {}

Object obj = new Line(new Point(1, 2), new Point(3, 4));

String result = switch (obj) {
    case Line(Point(int x1, int y1), Point(int x2, int y2)) ->
        "Xətt (" + x1 + "," + y1 + ") nöqtəsindən (" + x2 + "," + y2 + ") nöqtəsinədək";
    case Point(int x, int y) -> "Nöqtə (" + x + "," + y + ")";
    default -> "Naməlum obyekt";
};
System.out.println(result);

Çıxış:

Xətt (1,2)-dən (3,4)-dək

6. switch-də pattern matching-in xüsusiyyətləri və məhdudiyyətləri

Dəyişənlər yalnız case daxilində əlçatandır

Patterndə elan olunan dəyişən (məsələn, String s) yalnız uyğun case blokunun daxilində mövcuddur. Onun hüdudlarından kənarda əlçatan deyil.

switch (obj) {
    case String s -> System.out.println(s); // burada s görünür
    // System.out.println(s); // burada kompilyasiya xətası!
}

null-un işlənməsi

  • Köhnə obyektlər üzərindəki switch-də null ötürmək cəhdləri NullPointerException-a səbəb olurdu.
  • Yeni pattern matching switch-də null-u case null ilə açıq şəkildə işləmək mümkündür.

Guard-ifadələri (when)

Əlavə şərtlər (when) yalnız expression-üslublu switch-də (oxlu sintaksis ->) mövcuddur.

case String s when s.isEmpty() -> System.out.println("Boş sətir");

JDK və IDE tələbləri

  • switch-də pattern matching — Java 17 (preview) və Java 21+ (stabil) xüsusiyyətidir.
  • İşləməsi üçün JDK 21 və yeni imkanları dəstəkləyən IDE lazımdır (məsələn, IntelliJ IDEA 2023+).

7. Real tətbiqdə pattern matching switch-in tətbiqi

Tədris tətbiqinə baxaq — sadə tapşırıq-treker. Tutaq ki, abstrakt tapşırıq tipi və onun müxtəlif növləri var:

sealed interface Task permits SimpleTask, DeadlineTask, MeetingTask {}

final class SimpleTask implements Task {
    final String description;
    SimpleTask(String description) { this.description = description; }
}

final class DeadlineTask implements Task {
    final String description;
    final java.time.LocalDate deadline;
    DeadlineTask(String description, java.time.LocalDate deadline) {
        this.description = description;
        this.deadline = deadline;
    }
}

final class MeetingTask implements Task {
    final String topic;
    final java.time.LocalTime time;
    MeetingTask(String topic, java.time.LocalTime time) {
        this.topic = topic;
        this.time = time;
    }
}

Bütün məntiq bir yığcam switch-dədir:

Task task = new DeadlineTask("Layihəni təhvil vermək", java.time.LocalDate.of(2024, 7, 1));

String info = switch (task) {
    case SimpleTask st -> "Adi tapşırıq: " + st.description;
    case DeadlineTask dt -> "Müddətli tapşırıq: " + dt.description + ", " + dt.deadline + " tarixinədək";
    case MeetingTask mt -> "Görüş: " + mt.topic + " saat " + mt.time;
};
System.out.println(info);

Çıxış:

Müddətli tapşırıq: Layihəni təhvil vermək, 2024-07-01 tarixinədək

8. switch-də pattern matching istifadə edərkən tipik səhvlər

Səhv №1: null-un işlənməsini unutmaq. Əgər siz case null əlavə etməmisinizsə və obj null ola bilərsə — MatchException (və ya köhnə switch-də NullPointerException) alacaqsınız. Mümkünsə, null-u həmişə açıq şəkildə işləyin.

Səhv №2: sealed-sinifin bütün varislərini nəzərə almamaq. Əgər siz sealed-sinifdən istifadə edir və switch-də bütün variantları işləmirsinizsə, kompilyator xəta verəcək və ya default budağını tələb edəcək. İerarxiyanı genişləndirərkən yeni case-ləri əlavə etməyi unutmayın.

Səhv №3: pattern dəyişəni case blokundan kənarda əlçatan deyil. Pattern-də elan olunan dəyişən yalnız oxlu blok daxilində mövcuddur. Onu bu blokdan kənarda istifadə etmək cəhdi kompilyasiya xətasına səbəb olacaq.

Səhv №4: yeni xüsusiyyətləri köhnə JDK və ya köhnə IDE-də istifadə etmək. switch-də pattern matching Java 21+ və sizin IDE-də uyğun dəstək tələb edir. Köhnə versiya istifadə etsəniz — kompilyasiya xətası və ya düzgün olmayan ipucları ala bilərsiniz.

Səhv №5: guard-ifadələri ilə çaşqınlıq. when-i köhnə bloklu switch-də istifadə etməyə çalışırsınız? Alınmayacaq. Guardlar yalnız oxlu sintaksis üçün əlçatandır ->.

Səhv №6: açıq ierarxiyalarla işləyərkən default-budağı unutmaq. Əgər sizin switch yalnız sealed-siniflərlə işləmirsə, mütləq default əlavə edin — əks halda bütün variantlar işlənməyəcək.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Analitika sistemi üçün ədədlərin təsnifatı 🔢
Analitika sistemi üçün ədədlərin təsnifatı 🔢
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Baytarlıq klinikası üçün ağıllı ev heyvanlarının identifikasiya sistemi 🐕🐈🦜
Baytarlıq klinikası üçün ağıllı ev heyvanlarının identifikasiya sistemi 🐕🐈🦜
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION