Java java.lang.NumberFormatException hatası, sayıya dönüştürülmek istenen metnin hedef sayısal türün beklediği biçime uymaması nedeniyle oluşur. NumberFormatException, metnin hedef sayısal türe çevrilemediğini gösterir. Çözüm için yalnızca hatayı yakalamak yerine verinin nereden geldiğini ve dönüşüm satırında hangi biçimde bulunduğunu incelemek gerekir.
java.lang.NumberFormatException neden oluşur?
Java’da kullanıcı girdisi, dosyadan okunan veri veya başka bir String değer doğrudan int, double gibi sayısal türlere çevrilmeye çalışıldığında Java metnin beklenen sayı biçimine uyup uymadığını kontrol eder. Örneğin Integer.parseInt("42") geçerli bir tam sayı üretirken Integer.parseInt("42.5") çalışmaz. Benzer şekilde Double.parseDouble("12,5") ifadesindeki virgül, Java’nın beklediği ondalık gösterimle uyuşmadığı için hata oluşturabilir.
Resmî Java API dokümantasyonuna göre Integer.parseInt, sayı olmayan karakterler içeren, boş veya int aralığının dışında kalan metinlerde NumberFormatException oluşturur. Double.parseDouble da çözümlenemeyen bir sayı biçimiyle karşılaştığında aynı istisnayı üretir.
Teşhis sırasında dönüşüm yapılan satıra ve o satıra gelen değere odaklan:
- Veri kaynağını kontrol et: Değer
Scannerile mi alındı, dosyadan mı okundu, yoksa başka bir metinden mi üretildi? - Metni temizle: Başta veya sonda boşluk, görünmeyen karakter ya da boş giriş bulunup bulunmadığını incele.
- Biçimi doğrula: Değerin tam sayı mı, noktalı ondalık mı, yoksa yerel sayı yazımına sahip bir metin mi olduğunu belirle.
- Uygun parse yöntemini seç: Tam sayı için
Integer.parseInt, ondalıklı değer içinDouble.parseDoublekullanılmalıdır.
Yalnızca try-catch eklemek, veri kaynağındaki sorunu çözmez. Bu yaklaşım hatanın programı durdurmasını önleyebilir, ancak hatalı metnin neden geldiğini açıklamaz. Önce kaynak veriyi anlamlandırmak, ardından uygun temizleme ve doğrulama adımlarını uygulamak gerekir.
Integer.parseInt ve Double.parseDouble hangi girdileri kabul eder?
Integer.parseInt yalnızca tam sayı biçimindeki metinleri hedefler. Double.parseDouble ise tam sayıları ve Java’nın kabul ettiği noktalı ondalık gösterimleri double değerine dönüştürebilir. İki yöntem arasındaki farkı aşağıdaki örneklerle görebilirsin.
| Girdi | Integer.parseInt sonucu | Double.parseDouble sonucu | Teşhis |
|---|---|---|---|
"" |
NumberFormatException | NumberFormatException | Boş metin sayıya çevrilemez. |
" " |
NumberFormatException | NumberFormatException | Boşluklar temizlenince değer boş kalır. |
" 42 " |
NumberFormatException | 42.0 |
parseInt boşlukları kabul etmez; parseDouble baştaki ve sondaki boşlukları yok sayar. |
"42" |
42 |
42.0 |
Her iki yöntem için de geçerli bir sayısal gösterimdir. |
"12.5" |
NumberFormatException | 12.5 |
Ondalık kısım int için uygun değildir. |
"12,5" |
NumberFormatException | NumberFormatException | Virgül, bu yöntemlerin beklediği standart ondalık gösterimle uyuşmaz. |
Doğrudan parse işleminden önce metni uygun biçimde temizlemek iyi bir kontroldür. Ancak trim() kullanmak, virgüllü ondalık sayıyı otomatik olarak geçerli hâle getirmez. Virgülü körlemesine noktaya çevirmek de 1,234 değerinin ondalık sayı mı yoksa binlik ayraç içeren bir değer mi olduğunu belirsizleştirebilir. Yerelleştirilmiş sayı gösterimleri için veri kaynağının kuralı belirlenmeli ve gerektiğinde yerel ayarları destekleyen NumberFormat yaklaşımı değerlendirilmelidir.
Hatanın kaynağını adım adım nasıl teşhis edersin?
NumberFormatException, metnin hedef sayısal türe çevrilemediğini gösterir. Sorunu yalnızca try-catch ekleyerek kapatmak yerine, dönüşümden önce verinin nasıl geldiğini ve hangi biçimde olduğunu kontrol etmelisin.
- Veri kaynağını belirle ve gerçek değeri incele. Değer kullanıcıdan mı, dosyadan mı, bir API yanıtından mı geliyor? Dönüşümden hemen önce
System.out.println("Gelen değer: [" + metin + "]");gibi bir kontrolle gerçekStringiçeriğini gör. “Değer gerçekten boş mu?”, “Başında veya sonunda görünmeyen boşluk var mı?” sorularını yanıtla. - Temizlenebilir biçim sorunlarını gider. Kullanıcı girişinin başında ve sonunda boşluk bulunabilir. Bu nedenle dönüşümden önce
trim()ile çevresel boşlukları temizleyebilirsin. Ancak bu işlem harfleri, virgülü veya metnin ortasındaki hatalı karakterleri düzeltmez. - Biçimi parse işleminden önce doğrula. Boş değer, yalnızca boşluk, izin verilmeyen karakter, virgüllü ondalık ayırıcı veya kabul edilmeyen aralık gibi koşulları önceden kontrol et. Örneğin
87,5girdisi, nokta bekleyen bir doğrulama kuralına uymaz. Böyle bir durumda kullanıcıdan değeri uygun biçimde yeniden girmesini istemek, doğrudan hata yığını göstermekten daha açıklayıcıdır. - Verinin yapısına uygun parse yöntemini seç. Tam sayı bekliyorsan
Integer.parseInt(), ondalıklı bir değer bekliyorsanDouble.parseDouble()kullanılır. Sayısal tür seçimi, verinin gerçekten ne ifade ettiğine dayanmalıdır. Bir notu tam sayı olarak okumaya çalışmak, geçerli bir ondalık değerde yeni bir dönüşüm hatası oluşturabilir.
Bu dört aşamayı düzenli uygulamak, hatanın hangi noktada oluştuğunu görünür hâle getirir. Java’daki dönüşüm ve hata ayıklama mantığını uygulamalı çalışmak için Java özel ders programı içinde kişiye özel örnekler üzerinden ilerlenebilir.
Scanner ile güvenli not dönüştürme örneği
Scanner.nextLine() bir satırın metin olarak okunmasını sağlar. trim() baştaki ve sondaki uygun boşlukları kaldırır, matches() ise metnin tamamını belirlenen düzenli ifadeyle karşılaştırır. Bu kontrollerden sonra çağrılan Double.parseDouble(), dönüştürülemeyen bir metin için NumberFormatException oluşturabilir; bu nedenle son güvenlik katmanı olarak yakalanmalıdır.
import java.util.Scanner;
public class NotDonusturme {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.print("Notu girin: ");
String metin = scanner.nextLine().trim();
if (metin.isEmpty()) {
System.out.println("Boş değer girildi. Lütfen bir not yaz.");
} else if (!metin.matches("[0-9.,]+")) {
System.out.println("Hatalı metin: Sayısal bir değer girin.");
} else if (!metin.matches("\d+(\.\d+)?")) {
System.out.println("Biçim uyarısı: Ondalık ayırıcı olarak nokta kullanın.");
} else {
try {
double not = Double.parseDouble(metin);
if (not < 0 || not > 100) {
System.out.println("Aralık uyarısı: Not 0 ile 100 arasında olmalı.");
} else {
System.out.println("Geçerli not: " + not);
}
} catch (NumberFormatException e) {
System.out.println("Not dönüştürülemedi. Değeri tekrar girin.");
}
}
}
}
}
Beklenen örnek çıktılar:
87.5veya87.5: Geçerli not: 87.5- Boş giriş: Boş değer girildi.
abc: Hatalı metin: Sayısal bir değer girin.87,5: Biçim uyarısı: Ondalık ayırıcı olarak nokta kullanın.
Bu örnekte parseDouble() yalnızca boşluk, karakter ve sayı biçimi kontrollerinden sonra çalışır. Benzer dönüşüm sorularını çözerek seviyeni görmek için Java bilgi testini kullanabilirsin.
try-catch ne zaman kullanılmalı ve çözüm nasıl tamamlanır?
try-catch, NumberFormatException hatasını görünmez kılmak için değil, doğrulama adımlarından kaçan beklenmedik dönüşüm sorunlarını güvenli biçimde yönetmek için kullanılmalıdır. NumberFormatException, metnin hedef sayısal türe çevrilemediğini gösterir. Bu nedenle asıl çözüm, hatayı yakalamaktan önce verinin neden sayısal biçime uymadığını bulmaktır.
Örneğin kullanıcıdan not bilgisi alınıyorsa boş giriş, çevresel boşluk, virgüllü ondalık yazım veya harf içeren metin önce kontrol edilebilir. Buna rağmen dönüşüm aşamasında sorun oluşursa catch bloğu kullanıcıya anlaşılır geri bildirim vermek ve programın beklenmedik biçimde sonlanmasını önlemek için devreye girer.
try {
double not = Double.parseDouble(girdi.trim());
System.out.println("Girilen not: " + not);
} catch (NumberFormatException e) {
System.out.println("Lütfen sayı biçiminde bir not girin.");
}
Bu yapı tek başına yeterli değildir. Örneğin girdi boşsa, kullanıcıya yeniden giriş yaptırmak daha anlamlı olabilir. Kaynaktan gelen bir veri dönüştürülemiyorsa, yalnızca hata mesajı vermek yerine verinin nereden geldiğini ve hangi biçimde üretildiğini incelemek gerekir. Bir dosyadaki, formdaki veya API yanıtındaki değer beklenen sayısal alanla uyuşmuyorsa sorun çoğu zaman parseDouble satırından önce başlar.
Aşağıdaki yaklaşımlar genellikle sorunu gizler ve hata ayıklamayı zorlaştırır:
- Boş catch bloğu kullanmak: Hata oluşur, ancak nedenini ne kullanıcı ne de geliştirici görür.
- Her hatada aynı belirsiz mesajı göstermek: “Hata oluştu” yerine hangi alanın ve hangi biçimin beklendiği açıklanmalıdır.
- Geçersiz veriyi sessizce varsayılan değere çevirmek: Örneğin hatalı notu otomatik olarak
0yapmak, gerçek bir sıfır not ile hatalı girişi birbirine karıştırabilir.
Doğru tepki, verinin kaynağına göre değişir. Kullanıcı girdisinde değer yeniden istenebilir. Bir form alanında örnek biçim gösterilip giriş düzelttirilebilir. Dış bir kaynaktan gelen veride ise alanın üretildiği yer, boş değer olasılığı ve kullanılan ondalık ayırıcı incelenebilir. Ardından uygun dönüşüm yöntemi seçilir: tam sayılar için Integer.parseInt, ondalıklı değerler için Double.parseDouble kullanılmalıdır.
Java ile sistemli çalışırken bu teşhis sırasını alışkanlık hâline getirmek önemlidir: önce girdiyi incele, sonra temizle ve doğrula, en son dönüştür. Lise ve üniversite düzeyinde Java öğrenirken kişiye özel müfredatla ilerlemek isteyenler, birebir Java özel ders programının çalışma yapısını inceleyebilir.
Çözümü kontrol etmek için hangi adımlar uygulanır?
Hata mesajı ortadan kalktığında çözümün her veri türünde doğru çalıştığından emin olmak gerekir. Özellikle kullanıcı girdisiyle çalışan kodlarda yalnızca geçerli bir örnek denemek yeterli değildir. Aşağıdaki kontrol listesi, dönüşüm mantığını daha güvenilir biçimde gözden geçirmeye yardımcı olur:
- Boş giriş ve yalnızca boşluk içeren giriş denendi mi?
trim()ile baştaki ve sondaki boşluklar temizleniyor mu?- Tam sayı beklenen alan ile ondalık sayı beklenen alan birbirinden ayrıldı mı?
- Virgül ve nokta kullanımı için açık bir kural belirlendi mi?
abc,12aveya10.5gibi uygun olmayan girdilerde anlamlı geri bildirim veriliyor mu?- Dönüşüm başarılı olduktan sonra sayı aralığı ayrıca kontrol ediliyor mu?
Son madde özellikle önemlidir. Bir değer sayıya dönüşebilir, ancak uygulamanın kurallarına uygun olmayabilir. Örneğin not alanı 150 değerini teknik olarak dönüştürür; buna karşılık uygulamada kabul edilen aralığın dışında kalabilir. Bu yüzden biçim doğrulaması ile iş kuralı doğrulaması ayrı düşünülmelidir.
Farklı dönüşüm senaryolarında hangi yöntemin uygun olduğunu pekiştirmek için Java bilgi testiyle mevcut bilgini ölçebilirsin. Test, özellikle veri türleri, dönüşümler ve temel Java mantığıyla ilgili hangi konuların tekrar gerektirdiğini fark etmeye yardımcı olabilir.
Sık Sorulan Sorular
Integer.parseInt("10.5") neden NumberFormatException oluşturur?
Integer.parseInt yalnızca tam sayı biçimindeki metinleri dönüştürür. "10.5" ondalık ayırıcı içerdiği için tam sayı değildir. Bu değer için ondalıklı sayı gerekiyorsa Double.parseDouble tercih edilmelidir.
Double.parseDouble("12,5") neden hata verebilir?
Double.parseDouble, metin içindeki ondalık ayırıcı olarak genellikle noktayı bekler. "12,5" yerine "12.5" kullanılması gerekir. Virgül kabul edilecekse dönüşümden önce açık ve kontrollü bir dönüştürme kuralı uygulanmalıdır.
Sayıyı parse etmeden önce trim kullanmak neden önemlidir?
trim(), metnin başındaki ve sonundaki boşlukları kaldırır. Kullanıcının yanlışlıkla eklediği boşlukların dönüşümü etkilemesini önlemeye yardımcı olur. Ancak metnin içindeki harfleri veya yanlış ondalık biçimini düzeltmez.
try-catch eklemek java.lang.NumberFormatException hatasını tek başına çözer mi?
Hayır. try-catch hatayı yönetir, ancak geçersiz girdinin neden oluştuğunu düzeltmez. Kalıcı çözüm için veri kaynağı, temizleme işlemi, biçim doğrulaması ve sayı aralığı kontrolü birlikte ele alınmalıdır.
Sağlam bir dönüşüm akışı, yalnızca hata yakalamaya değil, sayıya çevrilecek metnin hangi koşullarda geçerli kabul edildiğini açıkça tanımlamaya dayanır.