İlk olarak, Kotlin'deki vakaları iyice kapsayan Null Safety hakkında her şeyi okumalısınız .
KOTLIN olarak, bunu olmadığından emin olmadan bir null değeri erişemez null
( koşullarda boş denetleniyor ) veya kesinlikle olmadığını iddia null
kullanarak !!
emin operatörü , bir ile erişen ?.
Güvenli Çağrısı son olarak muhtemelen bir şey veren ya null
bir ?:
Elvis Operatörünü kullanarak varsayılan değer .
Sorunuzun içinde 1 durum için size bunlardan birini kullanmak istiyorsunuz kod niyet bağlı seçenekler vardır ve hepsi deyimsel ama farklı sonuçlar var:
val something: Xyz? = createPossiblyNullXyz()
// access it as non-null asserting that with a sure call
val result1 = something!!.foo()
// access it only if it is not null using safe operator,
// returning null otherwise
val result2 = something?.foo()
// access it only if it is not null using safe operator,
// otherwise a default value using the elvis operator
val result3 = something?.foo() ?: differentValue
// null check it with `if` expression and then use the value,
// similar to result3 but for more complex cases harder to do in one expression
val result4 = if (something != null) {
something.foo()
} else {
...
differentValue
}
// null check it with `if` statement doing a different action
if (something != null) {
something.foo()
} else {
someOtherAction()
}
"Null işaretlendiğinde neden çalışıyor?" İçin, akıllı yayınlarda aşağıdaki arka plan bilgilerini okuyun .
Sorunuzun içinde 2 durum için birlikte söz konusu Map
geliştirici olarak varlık asla sonucun eminiz eğer, null
kullanımı !!
iddiası olarak emin operatörünü:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.get("a")!!
something.toLong() // now valid
veya başka bir durumda, harita null OLABİLİR, ancak varsayılan bir değer sağlayabildiğinizde, Map
kendisinin bir getOrElse
yöntemi vardır :
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.getOrElse("z") { 0 } // provide default value in lambda
something.toLong() // now valid
Arkaplan bilgisi:
Not: Aşağıdaki örneklerde, davranışı netleştirmek için açık türleri kullanıyorum. Tür çıkarımı ile, yerel değişkenler ve özel üyeler için normalde türler atlanabilir.
!!
Emin operatör hakkında daha fazla bilgi
!!
Operatör değeri olduğunu ileri sürer null
ya da NPE atar. Bu, geliştiricinin değerin asla olmayacağını garanti ettiği durumlarda kullanılmalıdır null
. Bunu bir iddia ve ardından akıllı bir oyuncu olarak düşünün .
val possibleXyz: Xyz? = ...
// assert it is not null, but if it is throw an exception:
val surelyXyz: Xyz = possibleXyz!!
// same thing but access members after the assertion is made:
possibleXyz!!.foo()
devamını oku: !! Emin Operatör
null
Kontrol ve Akıllı Yayınlar hakkında daha fazla bilgi
Null olabilecek bir türe bir null
çekle erişimi korursanız , derleyici akıllıca ifadenin gövdesindeki değeri null edilemez olarak kullanır. Bunun gerçekleşemeyeceği bazı karmaşık akışlar vardır, ancak yaygın durumlar için iyi çalışır.
val possibleXyz: Xyz? = ...
if (possibleXyz != null) {
// allowed to reference members:
possiblyXyz.foo()
// or also assign as non-nullable type:
val surelyXyz: Xyz = possibleXyz
}
Veya is
null olmayan bir tür olup olmadığını kontrol ederseniz :
if (possibleXyz is Xyz) {
// allowed to reference members:
possiblyXyz.foo()
}
Aynı şey, aynı zamanda güvenli yayınlama için 'ne zaman' ifadeleri için de geçerlidir:
when (possibleXyz) {
null -> doSomething()
else -> possibleXyz.foo()
}
// or
when (possibleXyz) {
is Xyz -> possibleXyz.foo()
is Alpha -> possibleXyz.dominate()
is Fish -> possibleXyz.swim()
}
Bazı şeyler , değişkenin daha sonra kullanılması için null
çekin akıllı yayın yapmasına izin vermez . Kullanımlara Yukarıdaki örnek hiçbir şekilde uygulamanın akışında mutasyona olabileceğini yerel bir değişken, ister val
veya var
bu değişken bir dönüşmeye için hiçbir fırsatı buldu null
. Ancak, derleyicinin akış analizini garanti edemediği diğer durumlarda, bu bir hata olacaktır:
var nullableInt: Int? = ...
public fun foo() {
if (nullableInt != null) {
// Error: "Smart cast to 'kotlin.Int' is impossible, because 'nullableInt' is a mutable property that could have been changed by this time"
val nonNullableInt: Int = nullableInt
}
}
Değişkenin yaşam döngüsü nullableInt
tam olarak görünmez ve diğer iş parçacıklarından atanabilir, null
kontrol boş bırakılamaz bir değere akıllı olarak dökülemez. Geçici bir çözüm için aşağıdaki "Güvenli Aramalar" konusuna bakın.
Akıllı oyuncu tarafından mutasyona uğramamaya güvenilemeyen başka bir durum, val
özel alıcıya sahip bir nesnenin özelliğidir. Bu durumda, derleyicinin değeri değiştiren şeyin görünürlüğü yoktur ve bu nedenle bir hata mesajı alırsınız:
class MyThing {
val possibleXyz: Xyz?
get() { ... }
}
// now when referencing this class...
val thing = MyThing()
if (thing.possibleXyz != null) {
// error: "Kotlin: Smart cast to 'kotlin.Int' is impossible, because 'p.x' is a property that has open or custom getter"
thing.possiblyXyz.foo()
}
devamını oku: Koşullarda null olup olmadığını kontrol etme
?.
Güvenli Arama operatörü hakkında daha fazla bilgi
Soldaki değer null ise güvenli çağrı operatörü null değerini döndürür, aksi takdirde sağdaki ifadeyi değerlendirmeye devam eder.
val possibleXyz: Xyz? = makeMeSomethingButMaybeNullable()
// "answer" will be null if any step of the chain is null
val answer = possibleXyz?.foo()?.goo()?.boo()
Bir listeyi yinelemek istediğiniz ancak null
boş olmasa da tekrarlamak istediğiniz başka bir örnek , yine güvenli arama operatörü işe yarar :
val things: List? = makeMeAListOrDont()
things?.forEach {
// this loops only if not null (due to safe call) nor empty (0 items loop 0 times):
}
Yukarıdaki örneklerden birinde, bir if
çek yaptığımız ancak başka bir iş parçacığının değeri değiştirdiği ve dolayısıyla akıllı bir döküm yapma şansımız olduğu bir vakamız vardı . Bunu let
çözme işleviyle birlikte güvenli çağrı operatörünü kullanmak için bu örneği değiştirebiliriz :
var possibleXyz: Xyz? = 1
public fun foo() {
possibleXyz?.let { value ->
// only called if not null, and the value is captured by the lambda
val surelyXyz: Xyz = value
}
}
devamını oku: Güvenli Aramalar
?:
Elvis Operatörü hakkında daha fazla bilgi
Elvis operatörü, operatörün solunda bir ifade olduğunda alternatif bir değer sağlamanıza olanak tanır null
:
val surelyXyz: Xyz = makeXyzOrNull() ?: DefaultXyz()
Bazı yaratıcı kullanımları da vardır, örneğin bir şey olduğunda bir istisna atın null
:
val currentUser = session.user ?: throw Http401Error("Unauthorized")
veya bir işlevden erken dönmek için:
fun foo(key: String): Int {
val startingCode: String = codes.findKey(key) ?: return 0
// ...
return endingValue
}
devamını oku: Elvis Operatörü
İlgili İşlevlere Sahip Boş İşleçler
Kotlin stdlib, yukarıda belirtilen operatörlerle gerçekten iyi çalışan bir dizi işleve sahiptir. Örneğin:
// use ?.let() to change a not null value, and ?: to provide a default
val something = possibleNull?.let { it.transform() } ?: defaultSomething
// use ?.apply() to operate further on a value that is not null
possibleNull?.apply {
func1()
func2()
}
// use .takeIf or .takeUnless to turn a value null if it meets a predicate
val something = name.takeIf { it.isNotBlank() } ?: defaultName
val something = name.takeUnless { it.isBlank() } ?: defaultName
İlgili konular
Kotlin'de, çoğu uygulama null
değerlerden kaçınmaya çalışır , ancak her zaman mümkün değildir. Bazen null
de mantıklı geliyor. Düşünülmesi gereken bazı yönergeler:
bazı durumlarda, yöntem çağrısının durumunu ve başarılı olursa sonucu içeren farklı dönüş türlerini garanti eder. Sonuç gibi kitaplıklar , kodunuzu da işleyebilecek bir başarı veya hata sonucu türü verir. Ve Kotlin için Kovenant adlı Promises kütüphanesi de aynı sözleri yerine getiriyor.
dönüş türleri olarak koleksiyonlar için null
, üçüncü bir "mevcut değil" durumuna ihtiyacınız olmadığı sürece her zaman a yerine boş bir koleksiyon döndürür . Kotlin'in bu boş değerleri yaratmak emptyList()
yaemptySet()
da yaratmak için yardımcı işlevleri vardır .
varsayılan veya alternatifiniz olan bir boş değer döndüren yöntemler kullanırken, varsayılan bir değer sağlamak için Elvis işlecini kullanın. Bir Map
kullanım durumunda, nullable değeri döndüren yöntem getOrElse()
yerine varsayılan bir değer oluşturulmasına izin verir . AynısıMap
get()
getOrPut()
Kotlin'in Java kodunun ?
hükümsüzlüğünden emin olmadığı Java'dan yöntemleri geçersiz kılarken, imzanın ve işlevselliğin ne olması gerektiğinden eminseniz , nulllability'yi geçersiz kılma işleminizden çıkarabilirsiniz. Bu nedenle geçersiz kılınan yönteminiz daha null
güvenlidir. Kotlin'de Java arabirimlerini uygulamak için de aynıdır, nullabiliteyi geçerli olduğunu bildiğiniz şekilde değiştirin.
Böyle gelince zaten yardımcı olabilir fonksiyonları, bakmak String?.isNullOrEmpty()
ve String?.isNullOrBlank()
hangi güvenle null değeri üzerinde işlem ve beklediğiniz yapabilirsiniz. Aslında, standart kütüphanedeki boşlukları doldurmak için kendi uzantılarınızı ekleyebilirsiniz.
gibi iddia fonksiyonları checkNotNull()
ve requireNotNull()
standart kütüphanede.
filterNotNull()
null'ları koleksiyonlardan kaldıran veya listOfNotNull()
olası bir null
değerden sıfır veya tek bir öğe listesi döndüren yardımcı işlevler .
Bir var Güvenli (null) dökme operatör mümkün değilse iyi ki NULL olmayan tip dönüş null bir döküm olanağı sağladığından yararlıdır. Ancak bunun için yukarıda belirtilen diğer yöntemlerle çözülmeyen geçerli bir kullanım durumum yok.