Kotlin Null Kontrolü (Null Safety)

Merhaba Arkadaşlar ,
Mobilhanem.com sitemiz üzerinden anlattığımız / yayınladığımız Kotlin Eğitim serimize bu dersimizde Kotlin Null kontrolü nasıl yapılır  , bir değişkene nasıl null değer atanır anlatmaya çalışacağız.

Java ile önceden uğraşmış ve ya şuan arkadaşlar bilirler ki Java’da en sık karşılaşılan hata tipi NullPointerException hata tipidir.  Bende Android ile uğraşan biri olarak en çok karşılaştığım hata da aynı şekilde NullPointerException hatasıdır. Bu hata nasıl oluşur derseniz kısaca şöyle bahsedeyim . Elinizde bir objeye bağlanmış bir referans var. Ve bu referans sonradan null bir değer atanmış ve ya initilaze edilmemiş (ilk değeri atanmamış) . Bu objenin herhangi bir değişkenine ve ya methoduna ulaşmaya çalıştığınızda NullPointerException hatası alırsınız.

NullPointerException hatası

Çok ufak bir java kodu örneği vereceğim. Java dili Kotlin diline benzediği için anlayacağınızı düşünüyorum.

public static void main(String []args){
 
 String str ="Mobilhanem Kotlin Null Safety";
 System.out.println("Stringin uzunluğu :" + str.length());
 
 str = null;
 System.out.println("Stringin uzunluğu :" + str.length());
}

Konsol Çıktısı:
Stringin uzunluğu :29
Exception in thread "main" java.lang.NullPointerException
	at HelloWorld.main(HelloWorld.java:8)

Yukarıda gördüğünüz gibi öncelikle String’e bir değer verdik ve str referansı’na atadık. Artık String objemizi str referansı ile çağırabiliriz.  String objemizin length() methodunu str.length(); şeklinde  çağırdık. length() methodu da bize String’imizin uzunluğunu döndü ve ekrana bastırdık. Sonrasında ise str referasına null değerini atadık ve artık str referansımız oluşturduğumuz String objesine değilde null değerine bağlandı.

String object

Yandaki şekilde gördüğünüz gibi öncelikle str referansımız bir String objesine bağlandı ve bu objenin içinde length , replace, intern,concat gibi methodlar mevcut. Biz bu methodlardan birini çağırdığımızda str referansının bağlandığı objeye ait method çalışacak ve ilgili işlemleri yapacak. Sonrasında ise str referansına null değerini bağladık. null değerinin herhangi bir methodu olmadığı için , çağırılacak bir fonksiyon ve ya değişken NullPointerException hatasına sebep olacaktır.

NullPointerException hatası CompileTime da değil RunTime’da ortaya çıkar. Yani kodu compile ederken bu hatayı yakalayamayız. Çalışırken bu hata ile karşılaşırız. Ancak yeni ideler(Intellij Idea , Android Studio …) muhtemel oluşabilecek NullPointer hatası için bizleri uyarmaktadır ancak compile etmemize engel olmamaktadır.

Not: Class , Obje , Method deyimlerine yabancı olan arkadaşlar endişelenmesin. İlerleyen derslerde bu konuları en derin şekilde inceleyeceğiz.

Şimdi şunu dediğinizi duyar gibiyim. Arkadaşım deli misin sen, neden referansa null değerini verdin. Hadi verdin verdikten sonra neden methodu çağırdın. Bunu sizlere göstermek için yaptım. Bir referans çok farklı sebeplerden dolayı null olabilir. Sunucudan cevap gelmeyebilir , developer hatası olabilir , kullandığınız bir kütüphanede kod hatası olabilir, multithread bir işlem yapıyor olabilirsiniz ve olmasını beklediğiniz sırada işlem gerçekleşmemiş olabilir vs vs. şeklinde birden çok şekilde null değer olabilir. Bu gibi durumlarda eğer önlemini almadıysak NullPointer hatası almamız kaçınılmaz oluyor ve uygulamamız / programımız crash oluyor.

Konumuz Java olmadığı için bu hatanın önüne nasıl geçeriz, ne gibi önlemler alabiliriz burada anlatmayacağım. Sadece bilgi olması amaçlı Java 8 ile birlikte gelen Optinal class‘ı nı inceleyebilirsiniz.

Kotlin Null ve Null Safety

Yukarıda nasıl NullPointer hatası alabiliriz sizlere anlatmaya çalıştım.  Kotlin dili NullPointer hatası almamamız için Java dilinden farklı bir syntax geliştirmiştir ve NullPointer hatası almak Java’ya göre daha zorlaştırlmıştır. Nasıl yapmıştır bunu diyorsanız yukarıda Java’da verdiğimiz örneği Kotlin dilinde hazırlamaya çalışalım.

kotlin null pointer

Yanda gördüğünüz gibi daha biz kodumuzu yazarken compiler hata fırlatıyor ve bizi uyarıyor  “Null can not be a value a non-null type String” hatası veriyor. Yani non-null bir tipe null değer atayamazsınız diyor. Bu kodu istesekte compile edemeyiz.

 

Non-Null Type (null olamayan tipler)

Yukarıda paylaştığım kodda gördüğümüz gibi bir referansa null değer ataması yaptığımız anda compile time da hata alıyoruz ve kodumuzu derleyemiyoruz. Böylelikle olası bir NullPointer hatasının önüne geçmiş olduk. Kotlin dilinde Null değer alamayan tiplere Non-Null Type adı verilmektedir. Biz bugüne kadar ki derslerimizde tanımladığımız tiplerin hepsi Non-Null tiptir. Non-Null tip tanımlamamız için extra birşey yapmamıza gerek yoktur.

var str : String = "Mobilhanem"
var sayi : Int = 5
var str2 : String
var sayi2 : Int

Yukarıdaki tiplerin hepsi Non-Null tiptir ve bu tiplere null değer atamaya çalıştığınız an compile hatası alırsınız ve  “Null can not be a value a non-null type String” veya “Null can not be a value a non-null type Int” hatası alırsınız. Böylelikle olası bir NullPointer hatasının önüne geçmiş olacaksınız. Peki ya bir değişkene nasıl null atayabiliriz derseniz buyurun Nullable tipi 🙂

Nullable Type (null olabilen tipler)

Kotlin Null ataması yapabilmek için değişkenleri aşağıdaki gibi tanımlamamız gerekir.

var str : String ? = "Mobilhanem"
var sayi : Int ? = 5
var str2 : String ?
var sayi2 : Int ?

Yukarıdaki gibi değişken tipimizin sonuna “?” soru işaretini ekliyoruz ve Kotlin’e değişkenimizin null değer alabileceğini söylüyoruz. Hepsini aşağıdaki gibi null’a eşitleyebiliriz.

var str : String ? = "Mobilhanem"
var sayi : Int ? = 5
var str2 : String ?
var sayi2 : Int ?

str = null
sayi = null
str2 = null
sayi2 = null

ve ya

var str : String ? = "Mobilhanem Kotlin Null Safety"
str = null //herhangi bir hata almazsınız çünkü ? eklediğimiz için null alabilir

Buraya kadar herşey çok güzel. Peki null alabilien bir tipi kodumuzda nasıl kullanacağız. Kullanımı non-null tiplerle aynı mı derseniz hayır aynı değil . Çünkü null olabilen tipteki bir değişkeni kodumuzda normal tipler gibi kullanırsak , yine NullPointer hatası alabiliriz çünkü herhangi bir yerde null olmuş olabilir.

var str : String ? = "Mobilhanem Kotlin Null Safety"
str = null //herhangi bir hata almazsınız çünkü ? eklediğimiz için null alabilir
print("Stringin uzunluğu : "+str.length) //HATAAA

 

kotlin null kontrolü

Yukarıdaki bu kod da yandaki resimde olduğu gibi Compile Time hatası verecektir ve kod derlenmeyecektir.  Çünkü Kotlinde bir değişkeni “?” ile tanımlarsak , yani nullable tip olarak tanımlarsak bu değişkeni direk kullanmamıza izin vermeyecektir.

Kullanmak için gerekli kontrollerini yap, önlemini al , yada güvenli olmayan yolu seç diyecektir. Güvenli olmayan yolu birazdan bahsedeceğim. Önce güvenli olan 2 yoldan bahsedelim.

1 – Null Kontrolü

Nullable tipteki bir değişkeni kullanmadan önce Kotlin sizden null olup olmadığının kontrolünü yapmanızı isteyecektir. Böylelikle kontrolü yaparak nullpointer hatasından kurtulabilirsiniz. Bu kontrolü nasıl yapacağız derseniz aşağıda örnek kodu paylaşıyorum.

if (str != null) {
    print("Stringin uzunluğu : "+ str.length) //str null değilse çalışacak.
}

Yukarıda gördüğünüz gibi if içinde nullable tipimizin (bizim örneğimizde “str”) null olup olmadığını kontrol ettik ve sonrasında ilgili metotları çağırdık. Böylelikle hatadan kurtulmuş olduk.

2- Safe Call Operatör Kullanma (?.)

İkinci yöntem ise safe call operatörü kullanma

str?.length

Yukarıdaki kod eğer str null değilse str’nin uzunluğunu eğer null’sa null değerini dönecektir. Yani hata fırlatmak yerine null değerini dönecektir.

Örnek Kullanım

var str : String ? = "Mobilhanem Kotlin Null Safety"
str = null //herhangi bir hata almazsınız çünkü ? eklediğimiz için null alabilir
print("Stringin uzunluğu : "+str?.length) 

Konsol çıktısı:
null

Direk “str.length” çağırdığımızda hata veriyor ve nullable tipin direk kullanılamıyacağını söylüyordu. “str?.length ” şeklinde çağırdığımızda kullanmamıza izin verdi ve str’nin null olma durumunda hata fırlatmak yerine geriye null değer döndü. Null kontrolüne göre biraz daha kolay bir kullanım. Zincir şeklinde çağıralacak methodlar içinde kullanımı daha kolaydır. Örneğin aşağıdaki kodda:

str?.replace("A","B")?.reversed()?.toLowerCase()?.trim()

Öncelikle String’deki tüm “A” ları “B” yaptık (replace), sonrasın stringi ters çevirdik (reverse) , tüm harfleri küçük harf yaptık (toLowerCase) ve başındaki – sonundaki boşlukları aldık (trim). Bu şekilde zincir biçiminde metotları çağıracaksak safe call operatörü kullanmamız gerekir. Yukarıdaki zincirde herhangi bir method null döndüğü an zincir kırılacak , devam etmeyecek ve direk null değeri geri dönecektir ve NullPointerException hatası oluşmayacaktır.

Elvis Operatör (?:)

Yukarıdaki zincir işlem null döndüğünde null değer kullanmak yerine başka bir değer kullanmak isterseniz elvis operatörü kullanabilirsiniz.

Aşağıda Elvis Operatörü olmadan kullanımı

val uzunluk : Int
if(str != null){
   uzunluk = str.length
}else{
   uzunluk = -1
}

Elvis Operatörü ile tek satırda aşağıdaki gibi yazabiliriz.

val uzunluk : Int = str?.length ?: -1

Az önce zincir şeklinde yazdığımız kodu aşağıdaki gibi yazarak herhanbi bir adımda null dönerse null değer dönmek yerine “String null” değerini döndük.

val str = str?.replace("A","B")?.reversed()?.toLowerCase()?.trim() ?: "Sring null"

!! Operatörü

Yukarıdaki yolları kullanarak NullPointerException hatası almayız. Birde az önce bahsettiğim güvenli olmayan yol var. !! Operatörü bahsettiğimiz güvenli olmayan yol.

Siz bu yolu seçerek bir nevi Kotlin’e null olup olmaması beni ilgilendirir sen işine bak diyoruz 🙂 Bu yüzden bu kullanımdan elimizden geldiğince uzak durmalıyız , hatta kullanmamalıyız.

var str : String ? = "Mobilhanem Kotlin Null Safety"
print("Stringin uzunluğu : "+str!!.length) 

Konsol Çıktısı:
Stringin uzunluğu : 29

Yukarıdaki kodda !! operatörü kullanarak Kotlin’e bu değer nullable (null alabilen) değer olsa bile ben herhangi bir kontrol yapmak istemiyorum, sende yapma ve bana str’nin değerini ver diyoruz. Yani kısaca null olması beni ilgilendirir diyoruz. Yukarıdaki kod hata vermeyecek çünkü str null değil.

Null olsa ne olacaktı peki

var str : String ? = "Mobilhanem Kotlin Null Safety"
str = null
    
print("Stringin uzunluğu : "+str!!.length)


Konsol Çıktısı:
Exception in thread "main" kotlin.KotlinNullPointerException
	at TestKt.main(test.kt:10)


Gördüğünüz gibi KotlinNullPointerException hatası alıyoruz. Bu yüzden !! operatörünü kullanmaktan kaçınmalıyız.

Bu dersimde anlatmak istediklerim bu kadar. Bir sonraki dersimde Kotlin Dilinde Fonksiyon kullanımı ile devam edeceğim.

Konu hakkında sorularınızı konu altından ve ya SoruCevap sitemizden sorabilirsiniz.

Tüm Kotlin derslerimiz için tıklayınız.

20

Taha Kırca

iOS & Android & Apple Watch Developer, Mobilhanem.com yazarı, Karadeniz Uşağu, Ordu Sevdalısı

2 Yorum

  • Var name : String? = null
    name = “mehmet”

    Çalıştığım kitapta önce null değer verilip sonra mehmet değeri veriliyor. Burada da baktım ama anlamadım. Neden böyke yapılıyor?

    • Bunu yapmasının sebebi nullable olan bir değişkenin yani soru işareti ile belirtilmiş bir değişkenin null değer alabileceği gibi başka bir değerde alabileceğini göstermiş.

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?