Kotlin
Brak bezpieczeństwa
Szukaj…
Typy zerowalne i niepozwalające
Typy normalne, takie jak String , nie są zerowalne. Aby umożliwić im przechowywanie wartości zerowych, musisz to wyraźnie zaznaczyć, wstawiając znak ? za nimi: String?
var string : String = "Hello World!" var nullableString: String? = null string = nullableString // Compiler error: Can't assign nullable to non-nullable type. nullableString = string // This will work however!
Bezpieczny operator połączeń
Aby uzyskać dostęp do funkcji i właściwości typów zerowalnych, musisz użyć specjalnych operatorów.
Pierwszy ?. , daje właściwość lub funkcję, do której próbujesz uzyskać dostęp, lub daje wartość null, jeśli obiekt ma wartość null:
val string: String? = "Hello World!" print(string.length) // Compile error: Can't directly access property of nullable type. print(string?.length) // Will print the string's length, or "null" if the string is null.
Idiom: wywoływanie wielu metod na tym samym obiekcie o sprawdzonej wartości zerowej
Elegancki sposób, aby wywołać wiele metod null sprawdzane obiektu korzysta Kotlin jest apply tak:
obj?.apply {
foo()
bar()
}
Wywoła to foo i bar na obj (co jest this w apply bloku) tylko wtedy, gdy obj jest niezerowe, omijając cały blok inaczej.
Aby wprowadzić zmienną zerowalną do zakresu jako odwołanie, które nie jest zerowalne, bez uczynienia z niej domyślnego odbiorcy wywołań funkcji i właściwości, możesz zastosować let zamiast apply :
nullable?.let { notnull ->
notnull.foo()
notnull.bar()
}
notnull może być nazwany jakikolwiek, a nawet pominięty i użyty przez niejawny parametr lambda it .
Inteligentne obsady
Jeśli kompilator może wywnioskować, że obiekt nie może być pusty w pewnym momencie, nie musisz już używać specjalnych operatorów:
var string: String? = "Hello!"
print(string.length) // Compile error
if(string != null) {
// The compiler now knows that string can't be null
print(string.length) // It works now!
}
Uwaga: Kompilator nie pozwala na inteligentne rzutowanie zmiennych, które można potencjalnie modyfikować między sprawdzaniem wartości zerowej a zamierzonym użyciem.
Jeśli zmienna jest dostępna spoza zakresu bieżącego bloku (ponieważ na przykład są członkami obiektu nielokalnego), musisz utworzyć nowe lokalne odwołanie, które możesz następnie inteligentnie rzutować i używać.
Wyeliminuj wartości zerowe z tablicy iterowalnej
Czasami musimy zmienić typ z Collection<T?> Na Collections<T> . W takim przypadku filterNotNull jest naszym rozwiązaniem.
val a: List<Int?> = listOf(1, 2, 3, null)
val b: List<Int> = a.filterNotNull()
Null Coalescing / Elvis Operator
Czasami pożądane jest, aby ocenić wyrażenie zerowalne w sposób „jeśli-inaczej”. Operator elvis, ?: , Może być użyty w Kotlinie w takiej sytuacji.
Na przykład:
val value: String = data?.first() ?: "Nothing here."
Powyższe wyrażenie zwraca "Nothing here" jeśli data?.first() lub same data dają wartość null , w przeciwnym razie wynik data?.first() .
Możliwe jest także zgłaszanie wyjątków przy użyciu tej samej składni, aby przerwać wykonywanie kodu.
val value: String = data?.second()
?: throw IllegalArgumentException("Value can't be null!")
Przypomnienie: wyjątki NullPointerException mogą być zgłaszane za pomocą operatora asercji (np.
data!!.second()!!Seconddata!!.second()!!)
Twierdzenie
!! sufiksy ignorują nullability i zwracają wersję tego typu inną niż null. KotlinNullPointerException zostanie KotlinNullPointerException , jeśli obiekt ma null .
val message: String? = null
println(message!!) //KotlinNullPointerException thrown, app crashes
Elvis Operator (? :)
W Kotlinie możemy zadeklarować zmienną, która może zawierać null reference . Załóżmy, że mamy odwołanie zerowe a , możemy powiedzieć „jeśli a nie jest zerowe, użyj go, w przeciwnym razie użyj wartości innej niż null x ”
var a: String? = "Nullable String Value"
Teraz może być null. a Kiedy więc potrzebujemy uzyskać dostęp do wartości a , musimy przeprowadzić kontrolę bezpieczeństwa, niezależnie od tego, czy zawiera ona wartość, czy nie. Możemy przeprowadzić tę kontrolę bezpieczeństwa za pomocą konwencjonalnej instrukcji if...else .
val b: Int = if (a != null) a.length else -1
Ale tu pojawia operator advance Elvis (Operator Elvis: ?: ). Powyżej, if...else operator może wyrazić za pomocą operatora Elvis, jak poniżej:
val b = a?.length ?: -1
Jeśli wyrażenie po lewej stronie ?: (Tutaj: a?.length ) nie jest puste, operator a?.length zwraca je, w przeciwnym razie zwraca wyrażenie po prawej stronie (tutaj: -1 ). Wyrażenie po prawej stronie jest oceniane tylko wtedy, gdy lewa strona jest pusta.