Wstęp
NullPointerException
(NPE
) czyli dostęp do referencji null
jest koszmarem wielu programistów, potrafi wystąpić w nieoczekiewanych sytuacjach i doprowadził już do nie jednego crasha
. Ze względu na swoją specyfikę znany jest jako The Billion Dollar Mistake
. Kotlin
został stworzony m.in. z myślą o eliminacji zagrożeń związanych z referencją null poprzez wykluczenie NPE z kodu. Jedynymi możliwościami, aby przypisać wartość null lub wywołać NPE jest jawne wywołanie KotlinNullPointerException
, użycie operatora !!, niespójność danych w stosunku do inicjalizacji (np. wyciek pamięci do referencji this) czy też kooperacja z kodem języka Java
(z którego może przyjść null).
Referencje
W Kotlin referencje, które nie mogą trzymać wartości null zwane są non-nullable references
, natomiast te które mogą przyjmować null zwane są nullable references
. Aby zmienna danego typu mogła przyjąć wartość null musi być w sposób jawny oznaczona w momencie definicji operatorem ?
. Jeśli zmienna nie deklaruje typu w sposób jawny i w momencie inicjalizacji przyjmuje wartość null wówczas jest typu Nothing
(nie posiada żadnej wartości i służy do oznaczenia nieosiągalnych miejsc w kodzie).
W celu uniknięcia sytuacji błędu kompilatora dostępu do właściwości zmiennej typu nullable można posłużyć się standardowym podejściem instrukcji warunkowych znanych z większości języków. Jeśli sprawdzana referencja jest stałą i nie przyjmuje wartości null, wówczas w dalszych warunkach klauzuli następuje automatyczne rzutowanie do typu non-null.
Jednakże Kotlin dostarcza kilka dedykowanych rozwiązań dostępu do właściwości zmiennych typu nullable.
Operator bezpiecznego wywołania
Bezpieczne wywołanie odbywa się za pomocą operatora ?.
co pozwala na dostęp do właściwości referencji typu nullable oraz nie wyklucza jego użycia w referencjach typu non-nullable. Jeśli zmienna jest null wówczas zwracana jest wartość null, a w przeciwnym wypadku wartość żądana.
Bezpieczne wywołanie może być użyteczne również w łańcuchu wywołań
. Jeśli któraś z właściwości łańcucha jest null wówczas zwracany jest null lub pomijana jest operacja przypisania wartości.
Jeśli żądana operacja ma wykonać się tylko dla referencji, które nie są null można wykorzystać w tym celu funkcję zakresu np.: let
.
Operator Elvis
Instrukcje warunkowe mogą być zastąpione operatorem Elvis
?:
, który zwraca wartość po swojej lewej stronie jeśli jest różna od null, a w przeciwnym wypadku wartość po prawej stronie. Ponadto zwracana wartość w przypadku wartości null może być zgłaszana wyrażeniem throw
, które zwraca obiekt typu Nothing
.
Operator asercji
Operator asercji not-null !!
konwertuje zmienną do typu non-nullable i wyrzuca wyjątek jeśli wartość jest równa null. Służy on do wywołania w sposób jawny NPE, co w Kotlinie nie jest w cale łatwe. W związku z tym jego użycie może stwarzać zagrożenia jakie wiążą się z NPE i jest niezalecane.
Wyjątki
Wszystkie klasy wyjątków
(exception
) w Kotlin są pochodnymi klasy Throwable
, natomiast nowe klasy wyjątków powinny dziedziczyć po klasie Exception
. Instancje klas wyjątków zawierają wiadomość, ślad stosu i opcjonalny powód wywołania, a rzucanie wyjątku odbywa się za pomocą wyrażenia throw
. Kotlin w przeciwieństwie do Java
nie posiada wyjątków typu checked
(wszystkie są unchecked
) w związku z czym metoda zgłaszająca wyjątek nie musi go deklarować.
Wywołanie newralgicznego kodu i ewentualne przechwytywanie wyjątku odbywa się w klauzuli try-catch-finally
, które jest wyrażeniem w związku z czym ostatnia instrukcja bloku try
lub catch
może zwracać rezultat. Warto zauważyć, że w związku brakiem wyjątków oznaczonych jako checked, kod wywołujący metodę, która może zgłaszać wyjątek nie musi umieszczać jej w klazuli try-catch.