Enum — Sabit Bir Seçenek Listesi
Önce şunu oku: final ve static — Kilitli Olan ve Ortak Olan
30 saniyede özet
enum, bir değerin alabileceği seçenekleri baştan sayar: yazım hatası derlenmez, switch eksik seçeneği yakalar. Enum aslında bir sınıftır; alan ve metot taşıyabilir. Veritabanına sırasını değil adını yazarsın.
Bir restoranın menüsünde üç yemek var. Garson “pizzza” yazarsa mutfak ne yapacağını bilemez; menüde öyle bir şey yok.
Kodda da bazı değerlerin yalnızca birkaç seçeneği vardır. Onları serbest metin yerine sabit bir menü olarak yazmanın yolu enum’dur.
Adım adım oku
- Durum String olarak tutulunca KARGODA, kargoda ve KARGODAA hepsi kabul ediliyor.
- enum Durum yalnızca üç seçenek tanımlıyor: HAZIRLANIYOR, KARGODA, TESLIM_EDILDI.
- Durum.KARGODAA yazmak derleme hatası verir; yazım hatası programa hiç giremez.
- Sabit bir menü: sürpriz yok.
-
Bayt: Kargodaki siparişleri listeledim, yarısı eksik çıktı!
-
Sen: Durumlar nasıl yazılmış?
-
Bayt: Kimisi KARGODA, kimisi kargoda, biri de KARGODAA. Hepsi metin.
-
Bayt: O zaman seçenekleri bir menüye yazalım. Menüde olmayan yazılamasın.
Metin yerine sabit bir liste
Bir enumBir değerin alabileceği seçenekleri baştan sayan tip. Listede olmayan bir değer derlenmez.Enum bir sınıftır: her sabit onun tek bir nesnesidir ve alan, kurucu, metot taşıyabilir. Sabitler tekil olduğu için == ile karşılaştırılabilir.Sözlükte gör → bir değerin alabileceği bütün seçenekleri baştan sayar. Listede olmayan bir değeri yazamazsın; derleyici durdurur.
enum Durum { HAZIRLANIYOR, KARGODA, TESLIM_EDILDI }
Durum d = Durum.KARGODA; // listeden seçildiDurum e = Durum.KARGODAA; // derleme hatası: böyle bir seçenek yokSwitch ifadesi enum’daki her seçeneği ele almak zorundadır. Enum’a yeni bir durum eklediğinde, onu unuttuğun her switch derlenmez.
String etiket = switch (d) { case HAZIRLANIYOR -> "Hazırlanıyor"; case KARGODA -> "Yolda"; case TESLIM_EDILDI -> "Teslim edildi";};Kafam karıştı, daha basit anlat
enum bir açılır listedir. Listede ne varsa o seçilebilir, fazlası değil. Yeni bir seçenek eklersen Java seni onu kullanmadığın yerlere kadar götürür.
Sipariş durumunu String yerine enum olarak tutmanın en önemli faydası nedir?
Enum aslında bir sınıf
Her enum sabiti, o enum sınıfının tek bir nesnesidir. Bu yüzden alanlar, bir kurucu ve metotlar taşıyabilir.
enum TransferTipi { FAST(new BigDecimal("0.00")), EFT(new BigDecimal("4.50")), SWIFT(new BigDecimal("25.00"));
private final BigDecimal ucret;
TransferTipi(BigDecimal ucret) { this.ucret = ucret; }
BigDecimal ucret() { return ucret; }}Böylece “tip EFT ise ücret şu” diye uzayan if-else zincirleri kaybolur: bilgi, ait olduğu seçeneğin içinde durur. Her sabit tek bir nesne olduğu için enum’ları == ile karşılaştırmak da güvenlidir.
Kafam karıştı, daha basit anlat
Her enum seçeneği küçük bir kartvizit gibidir: adının yanında kendi bilgisini de taşır. Ücreti sormak için tabloya bakmazsın, doğrudan kartvizite bakarsın.
İki enum değerini karşılaştırmak için `==` kullanmak güvenli midir?
Bu ücret hesabına yeni bir transfer tipi (KRIPTO) eklendi. Kod derlendi ama KRIPTO transferleri ücretsiz geçiyor. Sorunun kaynağı hangi satır?
Satır satır: metinden enum’a
Dışarıdan gelen bir metni (bir istek parametresi, bir dosya satırı) enum’a çevirmen gerekebilir.
`Durum.valueOf("kargoda")` çağrılınca ne olur? Cevabı göster
IllegalArgumentException. valueOf adı birebir, büyük-küçük harfiyle arar. “kargoda” diye bir sabit yok; “KARGODA” var.
Dışarıdan gelen metni güvenle çevirmek
String girdi = "kargoda";Durum d1 = Durum.valueOf(girdi);Durum d2 = Durum.valueOf(girdi.toUpperCase(Locale.ROOT));String ad = d2.name();int sira = d2.ordinal();Debug
valueOf Ad birebir aranır. "kargoda" bulunamaz ve IllegalArgumentException fırlatılır.
- d1
- = hata
Sol/sağ ok tuşlarıyla da gezebilirsin.
Dışarıdan gelen durum metni
Tohum 677418enum Durum { HAZIRLANIYOR, KARGODA, TESLIM_EDILDI }
Oynat ya da adımla: her adımda bir girdi okunur.
Şu an ne oldu?
String olarak sakla
Dört gerçek durum yazımı ve bir yazım hatası gelecek.
Görevler0/3
Yazım hatasını sessizce kaydetaçık
İpucu
Varsayılan ayarlar yeter.
Türkçe "i" yüzünden geçerli bir durumu reddetaçık
İpucu
Büyütmeyi makinenin diline bırak.
Bütün geçerli yazımları tanı, yazım hatasını reddetaçık
İpucu
Dilden bağımsız büyüt.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. Metin olarak saklayınca yazım hatası KARGODAA da bir durum gibi kaydedildi.
- “Durum.valueOf(girdi)” seç. Küçük harfle gelen her geçerli durum reddedildi.
- “Türkçe JVM” seçeneğini dene.
teslim_edildi, TESLİM_EDİLDİ’ye döndü ve reddedildi. - “Locale.ROOT” seç. Dört geçerli yazım tanındı, yazım hatası reddedildi.
Program ne yazdırır?
EnumMap ve EnumSet
Anahtarı enum olan bir map ya da enum’lardan oluşan bir küme gerekiyorsa, bunlar için yapılmış iki hazır yapı var.
Map<Durum, Integer> sayac = new EnumMap<>(Durum.class);Set<Durum> acik = EnumSet.of(Durum.HAZIRLANIYOR, Durum.KARGODA);İkisi de enum’ların sayısının sabit ve küçük olduğunu bilir; içeride basit bir dizi gibi çalışır. Sıraları da enum’daki tanım sırasıdır, bu yüzden çıktıları hep aynı düzende gelir.
Kafam karıştı, daha basit anlat
Seçenekler sabit ve az olduğunda, her birine ayrılmış numaralı bir çekmece yeter. EnumMap tam olarak bu çekmecelerdir.
Her sipariş durumu için bir sayaç tutacaksın. Hangi yapı en uygunudur?
Bir bankada para birimleri ve transfer tipleri tam böyle yazılır: her seçenek kendi kuralını taşır, hesaplama switch’e değil seçeneğin kendisine sorulur.
Derinleş · Transfer tipi ve veritabanında saklamak 3 dosya · ~43 satır · ilk okumada atlayabilirsin
Tuzaklar
Veritabanına sıra numarası yazmak. JPA’da @Enumerated’ın varsayılanı sıra numarasıdır (ordinalBir enum sabitinin listedeki sıfırdan başlayan sırası. İlk sabitin ordinal değeri 0'dır.Liste değişince değişir; bu yüzden kalıcı bir kimlik olarak (veritabanında, dosyada) kullanılmaz. Kalıcı olan sabitin adıdır: name().Sözlükte gör →). Enum’un ortasına yeni bir sabit eklersen eski kayıtların anlamı kayar; bu yüzden EnumType.STRING kullan.
Kullanıcı girdisini doğrudan valueOf’a vermek. Bilinmeyen bir değer IllegalArgumentException atar ve bu, kullanıcıya 500 hatası olarak dönebilir. Hatayı yakalayıp 400 olarak anlamlı bir mesajla dön.
Switch’e default yazmak. Default, yeni eklenen bir sabiti sessizce yutar. Enum üzerindeki switch ifadesinde default yazmazsan derleyici eksik seçeneği gösterir.
Bir JPA entity'sindeki enum alanında `@Enumerated` belirtilmemiş. Enum'un ortasına yeni bir sabit eklenince ne olur?
Kendini sına
Enum'da olmayan bir sabiti yazmak çalışma anında hata verir.
Enum sabitlerinin kendi alanları ve metotları olabilir mi?
Aklında kalacak üç şey
- 1 enum bir değerin alabileceği seçenekleri baştan sayar; listede olmayan bir değer derlenmez.
- 2 Enum bir sınıftır: her sabit kendi alanlarını ve davranışını taşıyabilir, böylece if-else zincirleri enum'un içine taşınır.
- 3 Enum'u veritabanına sıra numarasıyla değil adıyla yazarsın; araya yeni bir sabit eklemek eski kayıtların anlamını değiştirmemeli.
3 kart sonraki derste seni bekliyor