Java - Nedir bu NullPointerException?

LifeMCServer

Nether Yerlisi
Mesajlar
2,410
En iyi cevaplar
98
Beğeniler
2,463
Puanları
10,250
Ruh hali
Merhabalar!
Bir konuma daha hoş geldiniz. Bu sefer konumuz "null pointer exception", bu hata bir runtime (çalışma zamanı) hatasıdır, bu konuda hem bu hatayı anlatıp, hem de nasıl çözeceğinizden bahsedeceğim. Öncelikle koda erişiminiz yok ise çözmek için yapımcılara raporlamaktan başka şansınız yok diyebilirim. Hemen başlayalım isterseniz!

NullPointerException
İşte o en çok karşılaşılan hata.. Kendisine kısaltma olarak NPE'de denir. Bu hata bir null pointer (null referansı) üzerinde bir işlem yapmaya kalktığınızda ortaya çıkar. Null, hiçbir şeyi (aynı zamanda her şeyi, her çeşit değişkene uyum sağlar.) temsil eder. Yani hiçbir şeydir, yoktur. Şanslıyız ki bu hata çıktığında bize bir stack trace (hata yolu) verilir. Hatanın nerede, kaçıncı satırda çıktığını öğrenebiliriz. Fakat maalesef bazı dillerde olduğu gibi hangi karakterde çıktığını söylemiyor, sadece satırı veriyor. Ki bu çoğu zaman zaten bize yeterli olan kısım. Şimdi sırf test için aşağıya yazdığım kodu yürütüp çıkan hatayı inceleyeceğiz.

Kod:
Java:
package com.lifemcserver.test;

public final class NpeTest
{
    public static void main(final String[] args)
    {
        final String hello = null;
        System.out.println(hello.equalsIgnoreCase("hello world")); // eğer hello variablesi "hello world" ise true bastırır, değil ise false (fakat null ise hata verir)
    }
}


Bu kodda null olan bir string (yazı) üzerinde String#equalsIgnoreCase methodunu yürütmeye çalışıyoruz. Bu method bildiğiniz (veya bilmediğiniz) üzere bir stringin diğer string ile aynı değeri (yazıyı) içerip içermediğini büyük küçük harfleri yok sayarak kontrol etmemize yarıyor. Bu durumda yukarıdaki kodu çalıştırmaya çalışır isek kod hello variablesi (değişkeni) null olduğu için ve null bir referans üzerinden String#equalsIgnoreCase methodunu yürütemeyeceğimiz için, kod beklenildiği şekilde null pointer exception hatası verecektir. İşte bu yüzden this asla null olamaz (diğer, ilk konumda dediğim bir sözdü). Bir objenin methodu, ortada bir obje olmadan çağrılamaz.

Aynı şekilde sadece methodlar değil, bir objenin içerisindeki static olmayan hiçbir şeye ortada obje olmadan erişemeyiz. Eğer bir null üzerinden erişmeye çalışır isekde bu sefer de null pointer exception hatasını alırız.

Şimdi bu kodun verdiği hatayı inceleyip çözmeye çalışalım:
Java:
Exception in thread "main" java.lang.NullPointerException
    at com.lifemcserver.test.NpeTest.main(NpeTest.java:8)


Hatada ilk kısım hatanın hangi thread'de çıktığını gösteriyor, thread'ı nasıl çevirebilirim bilemiyorum ama şimdilik işlem diyebiliriz. Eğer Thread#setName kullanmadıysanız veya yeni bir thread açıp kodu oradan yürütmedi iseniz bu varsayılan olarak "main" olacaktır. Sonraki kısımda hangi hatanın çıktığını tam ve kendine özgü yolu ile gösteriyor: "java.lang.NullPointerException" yani bizim şu an da konuştuğumuz hata.

Fakat bizim asıl işimize yarayacak önemli kısım "at ..." kısımları. Bu kısımlara stack trace yani hata yolu diyoruz. Burada ilk baştaki "com.lifemcserver.test" kısmı kullandığımız paketin (adresin) adı. Yani NpeTest dosyasında package ...; yazarken com.lifemcserver.test yazdığımız için nasıl NullPointerException'da java.lang.NullPointerException yazıyor ise bizim test kodumuzda da ben com.lifemcserver.test adresini kullandığım için com.lifemcserver.test.NpeTest yazıyor. NpeTest burada hatanın çıktığı Java dosyasını temsil ediyor. Ondan sonra ki .main kısmı ise hangi methodda çıktığını temsil ediyor.

Fakat bunlar bize sadece genel bilgiyi sağlıyor, asıl kısım sondaki parantezler içerisinde gizli. Parantez içerisindeki yazıya bakar isek NpeTest.java:8 yazıyor. Buradaki NpeTest.java, hatanın çıktığı java dosyasını ve 8 ise de satır numarasını temsil ediyor. Peki neden iki adet NpeTest yazıyor, ilk başta da com.lifemcserver.test.NpeTest yazmışlar zaten diyeceksiniz, bunun nedeni tek bir java dosyasına bir den fazla class koyabilmemizdir. Konumuzda dönecek olur isek, :8 kısmı hatanın 8. satırda çıktığını belirtiyor.

Peki bu hatayı nasıl çözeriz?

Hatada bize hatanın NpeTest.java dosyasında yani yukarıda attığım kodda, 8. satırda çıktığı belirtiliyor. Peki 8. satırda ne mi var? hello.equalsIgnoreCase kısmı. Null bir referans olan "hello" adlı variable üzerinde String#equalsIgnoreCase methodunu yürütmeye çalıştığımız için karşımıza bu hata çıkıyor.

Ek:

NullPointerException hatası genelde sadece Java tarafından otomatik olarak atılan (throwlanan) bir hatadır. Yani bunu biz atar veya yakalar isek buna "bad practice" denir. Atmayı anladık, Java atıyor, biz kendimiz atar isek karışıklık çıkabilir. Peki neden yakalamakta "bad practice" olarak geçiyor? Çünkü, NullPointerException Java tarafından null bir referans üzerinde işlem yapmaya kalktığımızda otomatik olarak atılan hatadır. Bu hatayı yakalayıp yok saymak yerine null hatası verdiren referansı bulup çözmek (veya null kontrolü eklemek) daha mantıklıdır.

Bonus:

Yukarıdaki kodda hello null olsa bile hata verdirmeyip false bastırması için ufak bir değişiklik yapabiliriz.
Hata verdiren 8. satırı şu şekilde değiştirelim:

Java:
System.out.println("hello world".equalsIgnoreCase(hello)); // eğer hello variablesi "hello world" ise true bastırır, değil ise false


Burada "hello world" bir literal, final, constant veya read-only her ne derseniz artık, bir String'i temsil ediyor. Yani asla null olamaz. Bu durumda "hello world".equalsIgnoreCase(hello) kısmı eğer hello referansı null ise veya "hello world" değil ise false döndürüyor.

Eğer " işaretleri içerisine alarak yazdığınız literal bir string ile karşılaştırma yapmıyor iseniz ve hatayı çözmek istiyor iseniz de if (hello != null) şeklinde basit bir if kısmı ile halledebilirsiniz.


Konumuz bu kadardı,
Sonraki konularda tekrardan görüşmek üzere..​
 


Son düzenleme:

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,419
En iyi cevaplar
0
Beğeniler
1,542
Puanları
3,070
Güzel bir açıklama olmuş. Tabi OOP sistemi üzerinde yeterli bilgisi olmayan kişilerin yine anlamakta birazcık zorlanacağını düşünüyorum. Belki küçük örnekten sonra daha genel ve büyük bir örnek verebilirdin. "Bu hatayı ben nasıl yapabilirim ki?" tarzı sorulara cevap olması açısından yani. Sonuçta bu hata genelde biz null yazdığımız için değil de zincirleme metod çağırmalarında arada bir metod null döndürünce oluyor.

Bunun dışında NullPointerException yakalamak bazen gerekli olabilir. Ama tabi sadece hatayı çözmek için yakalamaktan bahsettiğini düşünürsek bilgi doğru ama belki yanlış yönlendirebilir.

Konu için ellerine sağlık!
 

LifeMCServer

Nether Yerlisi
Mesajlar
2,410
En iyi cevaplar
98
Beğeniler
2,463
Puanları
10,250
Ruh hali
Güzel bir açıklama olmuş. Tabi OOP sistemi üzerinde yeterli bilgisi olmayan kişilerin yine anlamakta birazcık zorlanacağını düşünüyorum. Belki küçük örnekten sonra daha genel ve büyük bir örnek verebilirdin. "Bu hatayı ben nasıl yapabilirim ki?" tarzı sorulara cevap olması açısından yani. Sonuçta bu hata genelde biz null yazdığımız için değil de zincirleme metod çağırmalarında arada bir metod null döndürünce oluyor.

Bunun dışında NullPointerException yakalamak bazen gerekli olabilir. Ama tabi sadece hatayı çözmek için yakalamaktan bahsettiğini düşünürsek bilgi doğru ama belki yanlış yönlendirebilir.

Konu için ellerine sağlık!

Haklısın, hataları zaten bilerek yapmıyoruz, çoğu modern IDE'de null variableler için önceden uyarı veriyor, daha çok methodlarda oluyor bu durum dediğin gibi.

NullPointerException yakalamanın gerekeceğini sanmıyorum, tabii eğer koda erişimin olmayan bir kütüphane de vesaire hata var ise yakalayabilirsin ama kendi kodunda gerekeceğini sanmıyorum yinede. (bahsettiğim kütüphane hatası iç hata, methoda verdiğin argümanlar vesaire null ise yine kendin çözmelisin, tabii argümanların null olması durumunda methoda kontroller eklenmeli ve NullPointerException yerine IllegalArgumentException tercih edilmeli.)

Yorumun için teşekkürler!
 

LifeMCServer

Nether Yerlisi
Mesajlar
2,410
En iyi cevaplar
98
Beğeniler
2,463
Puanları
10,250
Ruh hali
null kullanmayın, kullandırtmayın.
One More Recipe Against NULL

Null doğru kullanılması gereken bir şey fakat zaten Java çoğu durumda hata verdirdiği için hataları konuda anlattığım şekilde takip ederek hatayı kolayca çözebiliriz.

Java'da her şey null olabilir, nullable type olayı yok. Yani bana kalırsa null değer yollamak / almak her zaman mümkün. Gerekli kontroller ile veya yöntemler ile çözülebilir, attığın linkte de bunun bir yönteminden bahsediyor.

Ek bir önlem istiyor isek de Eclipse (org.eclipse.jdt.annotations) ve IntelliJ (jetbrains.annotations) gibi IDE'lerin kendi kütüphaneleri var daha iyi null analizi için (bunlar dışında FindBugs / SpotBugs ve SonarLint de var).
 

Elfen

Kızıltaş Madencisi
Mesajlar
508
En iyi cevaplar
0
Beğeniler
596
Puanları
1,230
Null doğru kullanılması gereken bir şey fakat zaten Java çoğu durumda hata verdirdiği için hataları konuda anlattığım şekilde takip ederek hatayı kolayca çözebiliriz.

Java'da her şey null olabilir, nullable type olayı yok. Yani bana kalırsa null değer yollamak / almak her zaman mümkün. Gerekli kontroller ile veya yöntemler ile çözülebilir, attığın linkte de bunun bir yönteminden bahsediyor.

Ek bir önlem istiyor isek de Eclipse (org.eclipse.jdt.annotations) ve IntelliJ (jetbrains.annotations) gibi IDE'lerin kendi kütüphaneleri var daha iyi null analizi için (bunlar dışında FindBugs / SpotBugs ve SonarLint de var).
Java'da sen veya kullandığın kütüphanelerden birisi null kullanmadığı sürece hiçbir şey null olmaz. Null olmazsa NullPointerException'da olmaz. NullPointerException olmazsa kontrol etmene ve hatalarla uğraşmana gerek kalmaz. Hatalarla uğraşmana gerek kalmazsa değerli vaktini daha iyi harcayabilirsin. Vaktini daha iyi harcarsan daha mutlu yaşarsın. Daha mutlu yaşarsan da daha mutlu ölürsün.
 

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,419
En iyi cevaplar
0
Beğeniler
1,542
Puanları
3,070
Java'da sen veya kullandığın kütüphanelerden birisi null kullanmadığı sürece hiçbir şey null olmaz. Null olmazsa NullPointerException'da olmaz. NullPointerException olmazsa kontrol etmene ve hatalarla uğraşmana gerek kalmaz. Hatalarla uğraşmana gerek kalmazsa değerli vaktini daha iyi harcayabilirsin. Vaktini daha iyi harcarsan daha mutlu yaşarsın. Daha mutlu yaşarsan da daha mutlu ölürsün.
Null dediğimiz şey bir durumun gerçekten istenmemiş bir sonuca ulaştığını belirtmenin en kesin yoludur. Verdiğin konuda bir sürü yöntem sunulduğu doğru ama ya Java için uyarlanamaz ya da kesin olmayan yöntemler bunlar. Mesela default değer döndürme üzerinde durulmuş ama bu yöntemle methodun gerçekten sonuca ulaşıp ulaşmadığını anlayamazsın ve çoğu zaman anlaman gerekir. Ya da gerçekten aşırı consistent bir sistem kullanarak (OpenGL'in yaptığı gibi) kendi enum değerlerinle işlem yaptırabilirsin ama o denli bir kütüphane yazmadığın sürece gerçekten null kullanmak en basit ve en kesin yol.
 

Elfen

Kızıltaş Madencisi
Mesajlar
508
En iyi cevaplar
0
Beğeniler
596
Puanları
1,230
Null dediğimiz şey bir durumun gerçekten istenmemiş bir sonuca ulaştığını belirtmenin en kesin yoludur. Verdiğin konuda bir sürü yöntem sunulduğu doğru ama ya Java için uyarlanamaz ya da kesin olmayan yöntemler bunlar. Mesela default değer döndürme üzerinde durulmuş ama bu yöntemle methodun gerçekten sonuca ulaşıp ulaşmadığını anlayamazsın ve çoğu zaman anlaman gerekir. Ya da gerçekten aşırı consistent bir sistem kullanarak (OpenGL'in yaptığı gibi) kendi enum değerlerinle işlem yaptırabilirsin ama o denli bir kütüphane yazmadığın sürece gerçekten null kullanmak en basit ve en kesin yol.
"anlayamazsın ve çoğu zaman anlaman gerekir" örnek verebilir misin? "null" kullanmanın daha mantıklı veya zorunlu olduğunu düşündüğün bir örnek verirsen sana aksini ispat edebilirim.

"null" denen şey, low-level dillerde, erişilmeye çalışılan bir pointerın herhangi bir karşılığı olmadığında karşımıza çıkar. "null" Java'ya C'den gelmiştir. Java'da "null" ün bulunmasının tek sebebi hali hazırdaki geliştiricilerin "null" e alışkın olmalarıdır. "null" bir nevi "0" (sıfır) a eşittir ve nesne yönelimli bir dilde bulunması tamamıyla saçmalıktır. Çünkü nesne yönelimli dillerde "pointer" yani ramdeki konumu temsil eden bir şey bulunmaz.

"null" ün kendisini icat eden adam tarafından bile sevilmediğini de eklemek isterim: Null References: The Billion Dollar Mistake
 

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,419
En iyi cevaplar
0
Beğeniler
1,542
Puanları
3,070
"anlayamazsın ve çoğu zaman anlaman gerekir" örnek verebilir misin? "null" kullanmanın daha mantıklı veya zorunlu olduğunu düşündüğün bir örnek verirsen sana aksini ispat edebilirim.

"null" denen şey, low-level dillerde, erişilmeye çalışılan bir pointerın herhangi bir karşılığı olmadığında karşımıza çıkar. "null" Java'ya C'den gelmiştir. Java'da "null" ün bulunmasının tek sebebi hali hazırdaki geliştiricilerin "null" e alışkın olmalarıdır. "null" bir nevi "0" (sıfır) a eşittir ve nesne yönelimli bir dilde bulunması tamamıyla saçmalıktır. Çünkü nesne yönelimli dillerde "pointer" yani ramdeki konumu temsil eden bir şey bulunmaz.

"null" ün kendisini icat eden adam tarafından bile sevilmediğini de eklemek isterim: Null References: The Billion Dollar Mistake
Yıllardır yazılımcıların değişik değişik şeylere düşmanlık etmesini hala anlayamıyorum. "Null kötü asla kullanmayın", "Static ağlatır kullanmayın" gibi gibi şeyler cidden çok can sıkıcı bir hal alıyor. Eğer kullanmayı biliyorsan en kötü yazılım mekaniğini elindeki en iyi kaynak bile yapabilirsin. Yazılıma yeni başlayan kişileri de bu tür tekdüze kurallarla lütfen artık yanlış taraflara çekmeyelim. Ve şunu da unutmayalım: Bir yazılımcı, elindeki her kaynağı her açıdan en iyi şekilde kullanabilen kişi olmalıdır. Bu da bir şeyleri kesin olarak kenara atmanın tabii ki dışında bir durum.
 

GodofMilker

Nether Yerlisi
Mesajlar
2,196
En iyi cevaplar
0
Beğeniler
2,563
Puanları
6,890
Yıllardır yazılımcıların değişik değişik şeylere düşmanlık etmesini hala anlayamıyorum. "Null kötü asla kullanmayın", "Static ağlatır kullanmayın" gibi gibi şeyler cidden çok can sıkıcı bir hal alıyor. Eğer kullanmayı biliyorsan en kötü yazılım mekaniğini elindeki en iyi kaynak bile yapabilirsin. Yazılıma yeni başlayan kişileri de bu tür tekdüze kurallarla lütfen artık yanlış taraflara çekmeyelim. Ve şunu da unutmayalım: Bir yazılımcı, elindeki her kaynağı her açıdan en iyi şekilde kullanabilen kişi olmalıdır. Bu da bir şeyleri kesin olarak kenara atmanın tabii ki dışında bir durum.
Oluşturan ilk kişi hata yapıp eklemişse kullanmak çok da mantıklı olmuyor sonuçta*
Niye 2 çeşit null yok mesela :(
Dilleri yazanlar da insan ve zamanına göre hata yapmış olabilirler*
(null ne kadar gerekli savaşın bnne .s)
 

Elfen

Kızıltaş Madencisi
Mesajlar
508
En iyi cevaplar
0
Beğeniler
596
Puanları
1,230
Yıllardır yazılımcıların değişik değişik şeylere düşmanlık etmesini hala anlayamıyorum. "Null kötü asla kullanmayın", "Static ağlatır kullanmayın" gibi gibi şeyler cidden çok can sıkıcı bir hal alıyor. Eğer kullanmayı biliyorsan en kötü yazılım mekaniğini elindeki en iyi kaynak bile yapabilirsin. Yazılıma yeni başlayan kişileri de bu tür tekdüze kurallarla lütfen artık yanlış taraflara çekmeyelim. Ve şunu da unutmayalım: Bir yazılımcı, elindeki her kaynağı her açıdan en iyi şekilde kullanabilen kişi olmalıdır. Bu da bir şeyleri kesin olarak kenara atmanın tabii ki dışında bir durum.
Sen bana mantıklı bir örnek verebilecek misin ondan haber ver kardeşim. Konuyu farklı yerlere çekmeye çalışma gereksiz yere.
 

LifeMCServer

Nether Yerlisi
Mesajlar
2,410
En iyi cevaplar
98
Beğeniler
2,463
Puanları
10,250
Ruh hali
Sen bana mantıklı bir örnek verebilecek misin ondan haber ver kardeşim. Konuyu farklı yerlere çekmeye çalışma gereksiz yere.


Aksine çok iyi bir yere değinmiş. Bu arada ben konumda null'u kullanın kullandırtın demedim zaten hatayı anlattım. Null kullan kullanma stack trace okumayı vesaire de yazdım. Sadece NPE'ye özel bir şey değil neredeyse tüm hataları bu şekilde çözersin. Null Java'da bir keyword, Oracle'nin resmi sitesinde de "deprecated" veya "shouldn't be used" tarzı bir ifade yok. Bir sitenin bir makalesinde "you should not use null" veya bir forumda bir mesajda "null kullanmayın, kullandırtmayın" yazısı gördü diye kimse de null kullanmayı bırakmaz. Seni bilemem tabii.

Bu yüzden lütfen her şeye karşı olmayı bırakın. Bir şey hatalara veya buglara sebep olabiliyor diye neden kötü, kullanılmaz, gereksiz olsun? (kaldı ki o hatalar bugları daha kolay bulmamız için yapıldı) Java'ya sadece insanlar null'a alıştı diye eklendi diyorsun Null'u bulan adamın pişmanlığını yüz yüze görüşüp öğrendiğin gibi Java'yı bulan kişiyle de yüz yüze görüştün sanırım? Bu yöntemler çok eskimedi mi ya? "Ya kardeşim menim yapımcısı bile şöyle diyor sen daha ne konuşuyorsun?" falan. Ha bir de kardeşimli mardeşimli konuşmak var unutmuşum. "Static çöp abi JVM'ye yapışıyor. Java Object Oriented dil sen niye kullanmak static?", "Null çöp beyler kullanmayın kullandırtmayın bulunduğunuz ortamda kullanınıda linçleyin"

Yıllardır yazılımcıların değişik değişik şeylere düşmanlık etmesini hala anlayamıyorum. "Null kötü asla kullanmayın", "Static ağlatır kullanmayın" gibi gibi şeyler cidden çok can sıkıcı bir hal alıyor. Eğer kullanmayı biliyorsan en kötü yazılım mekaniğini elindeki en iyi kaynak bile yapabilirsin. Yazılıma yeni başlayan kişileri de bu tür tekdüze kurallarla lütfen artık yanlış taraflara çekmeyelim. Ve şunu da unutmayalım: Bir yazılımcı, elindeki her kaynağı her açıdan en iyi şekilde kullanabilen kişi olmalıdır. Bu da bir şeyleri kesin olarak kenara atmanın tabii ki dışında bir durum.
 

GodofMilker

Nether Yerlisi
Mesajlar
2,196
En iyi cevaplar
0
Beğeniler
2,563
Puanları
6,890
Aksine çok iyi bir yere değinmiş. Bu arada ben konumda null'u kullanın kullandırtın demedim zaten hatayı anlattım. Null kullan kullanma stack trace okumayı vesaire de yazdım. Sadece NPE'ye özel bir şey değil neredeyse tüm hataları bu şekilde çözersin. Null Java'da bir keyword, Oracle'nin resmi sitesinde de "deprecated" veya "shouldn't be used" tarzı bir ifade yok. Bir sitenin bir makalesinde "you should not use null" veya bir forumda bir mesajda "null kullanmayın, kullandırtmayın" yazısı gördü diye kimse de null kullanmayı bırakmaz. Seni bilemem tabii.

Bu yüzden lütfen her şeye karşı olmayı bırakın. Bir şey hatalara veya buglara sebep olabiliyor diye neden kötü, kullanılmaz, gereksiz olsun? (kaldı ki o hatalar bugları daha kolay bulmamız için yapıldı) Java'ya sadece insanlar null'a alıştı diye eklendi diyorsun Null'u bulan adamın pişmanlığını yüz yüze görüşüp öğrendiğin gibi Java'yı bulan kişiyle de yüz yüze görüştün sanırım? Bu yöntemler çok eskimedi mi ya? "Ya kardeşim menim yapımcısı bile şöyle diyor sen daha ne konuşuyorsun?" falan. Ha bir de kardeşimli mardeşimli konuşmak var unutmuşum. "Static çöp abi JVM'ye yapışıyor. Java Object Oriented dil sen niye kullanmak static?", "Null çöp beyler kullanmayın kullandırtmayın bulunduğunuz ortamda kullanınıda linçleyin"
Birisi şunu yapmayın deyip nedenini açıklarsa niye yapasın o şeyi :(
 

Üst