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.