I, Nullable type
- Một trong những vấn đề hay gặp phải nhất với các programming language (bao gồm cả java) là sử dụng 1 null variable (reference) sẽ gây ra null reference exception.
- Trong java, bạn sẽ gặp phải
NullPointerException
hayNPE
. - Kotlin cung cấp các công cụ để giúp bạn loại bỏ vấn đề trên trong code.
- Do đó kotlin sẽ gặp phải NPE ở 1 trong các trường hợp sau:
- 1, Bạn trực tiếp gọi
throw NullPointerException()
. - 2, Sử dụng toán tử
!!
trên 1 null reference (mình sẽ nói sau). - 3, Gặp vấn đề khi sử dụng platform type hoặc do java code. Ví dụ: add
null
element vàoMutableList<String?>
. - 4, Liên quan tới việc khởi tạo của 1 object.
- 1, Bạn trực tiếp gọi
- Kotlin giúp chúng ta phân biệt nullable reference và non-nullable reference.
- Ví dụ 1:
1 | var a: String = "abc" // Regular initialization means non-null by default |
- Ví dụ 2:
1 | var b: String? = "abc" // can be set null |
II, Check điều kiện null
- Cách xử lý thông thường giống với java là chúng ta sẽ check xem b có null hay không.
- Ví dụ 3: nếu
b
khác null thì gánl = b.length
không thìl = -1
1 | val l: Int = if (b != null) b.length else -1 |
III, Safe call
- Kotlin cung cấp 1 công cụ khác là
safe call
, nó thêm?.
vào sau variable. - Ví dụ 4:
1 | val a = "Kotlin" |
Safe call chain
có dạng làv1?.v2?.v3[?.v4[?..]]
. Nó rất hữu ích vì nó sẽ returnnull
nếu bất cứ variable nào bịnull
.- Ví dụ 5: Nếu
parent
,parent.child1
hayparent.child1.child2
returnnull
, safe call chain cũng sẽ returnnull
1 | parent?.child1?.child2?.child3 |
- Trong phép gán
=
, safe call có thể được đặt bên trái của=
. Nếu 1 variable trongsafe call chain
returnnull
, việc gán sẽ bị bỏ qua và biểu thức bên phải=
sẽ không được gọi. - Ví dụ 6: Nếu
person
hayperson.department
trả về null,managersPool.getManager()
sẽ không được gọi, do đó việc gán bị bỏ qua
1 | person?.department?.head = managersPool.getManager() |
IV, Toán tử Elvis
- Kotlin cũng cung cấp 1 toán tử khác đó là
evils
, nó được viết là?:
. - Nếu expression bên trái của evils khác
null
, kết quả của evils là expression bên trái đó. Nếu không, kết quả của evils là expression bên phải. - Ví dụ 7: Viết lại ví dụ 3 bằng toán tử evils
1 | val l = b?.length ?: -1 |
- Trong kotlin,
return
vàthrown
cũng là các expression, do đó chúng có thể được dùng trong expression bên phải của evils. - Ví dụ 8:
1 | val parent = node.getParent() ?: return null |
V, Toán tử !!
- Toán tử
!!
không được khuyến khích vì nó xác nhận rằng variable không thể bị null (mặc dù variable vẫn có thể bị null) và sẽ throwNPE
khi variable bị null. - Ví dụ 9: nếu
b
có giá trị null thì code sẽ throwNPE
1 | val l = b!!.length |
VI, Safe cast
- Toán tử cast có thể gây ra
ClassCastException
nếu kiểu dữ liệu của variable không thuộc kiểu của class được cast. - Kotlin cung cấp
safe cast
, nó được viết làas?
. - Safe cast sẽ trả về null nếu việc cast không thành công.
- Ví dụ 10: nêu cast không thành công thì
i
sẽ có giá trị null
1 | val i: Int? = a as? Int |
V, Null type trong các collection
- Nếu bạn sử dụng collection cho phép các nullable element, bạn có thể lọc để chọn ra những toán tử khác null bằng filterNotNull().
- Ví dụ 11: kết quả của
nonNullNumbers
là[1, 2, 4]
1 | val numbers: List<Int?> = listOf(1, 2, null, 4) |