Dùng các biến có thuộc tính rỗng
null là gì?
Trong Bài 1, bạn đã được học khi khai báo một biến, bạn cần chỉ định ngay giá trị cho biến đó. Ví dụ: khi khai báo một biến favoriteActor, bạn có thể chỉ định ngay giá trị chuỗi "Sandra Oh" cho biến đó.
val favoriteActor = "Sandra Oh"

Tuy nhiên, nếu bạn không có diễn viên yêu thích thì sao? Bạn nên chỉ định cho biến một giá trị "Nobody" hoặc "None". Đây không phải là phương pháp hay vì chương trình của bạn diễn giải biến favoriteActor có giá trị "Nobody" hoặc "None" thay vì không có giá trị. Trong Kotlin, bạn có thể dùng null để cho biết không có giá trị nào liên kết với biến.

Để sử dụng null trong mã, hãy làm theo các bước sau:
- Trong Kotlin Playground, hãy thay thế nội dung trong phần nội dung của hàm
main()bằng một biếnfavoriteActorđã đặt thànhnull:
fun main() {
val favoriteActor = null
}
- In giá trị của biến
favoriteActorbằng hàmprintln()rồi chạy lập trình này:
fun main() {
val favoriteActor = null
println(favoriteActor)
}
Kết quả sẽ có dạng như đoạn mã này:
null
Chỉ định lại biến bằng null
Trước đây, bạn đã biết rằng có thể chỉ định lại các biến được xác định bằng từ khoá var cho các giá trị khác nhau cùng loại. Ví dụ: bạn có thể chỉ định lại một biến name được khai báo bằng một tên cho tên khác, miễn là tên mới thuộc loại String.
var favoriteActor: String = "Sandra Oh"
favoriteActor = "Meryl Streep"
Đôi khi sau khi khai báo một biến, bạn có thể chỉ định biến đó cho null. Ví dụ: sau khi khai báo diễn viên yêu thích, bạn quyết định không muốn tiết lộ diễn viên mình yêu thích. Trong trường hợp này, bạn nên chỉ định biến favoriteActor cho null.
Hiểu về các biến không rỗng và biến rỗng
Để chỉ định lại biến favoriteActor cho null, hãy làm theo các bước sau:
- Thay đổi từ khóa
valthành từ khóavarvà sau đó chỉ định biếnfavoriteActorlà một loạiStringvà chỉ định biến đó cho tên của diễn viên bạn yêu thích:
fun main() {
var favoriteActor: String = "Sandra Oh"
println(favoriteActor)
}
- Xóa hàm
println():
fun main() {
var favoriteActor: String = "Sandra Oh"
}
- Chỉ định lại biến
favoriteActorchonullrồi chạy lập trình này:
fun main() {
var favoriteActor: String = "Sandra Oh"
favoriteActor = null
}
Bạn sẽ nhận được thông báo lỗi sau:

Trong Kotlin, có sự khác biệt giữa các loại giá trị rỗng và không rỗng:
- Loại có giá trị rỗng là các biến có thể lưu giữ dữ liệu
null. - Loại không có giá trị rỗng là các biến không thể lưu giữ dữ liệu
null.
Một loại chỉ có thể rỗng nếu bạn cho phép lưu giữ dữ liệu null một cách rõ ràng. Như thông báo lỗi hiển thị ở trên, loại dữ liệu String là loại không rỗng, do đó, bạn không thể chỉ định lại biến đó thành null.

Để khai báo biến rỗng trong Kotlin, bạn cần thêm một toán tử ? vào cuối loại biến đó. Ví dụ: loại String? có thể chứa một chuỗi hoặc null, trong khi loại String chỉ có thể chứa một chuỗi. Để khai báo một biến rỗng, bạn cần thêm loại rỗng một cách rõ ràng. Nếu không có loại rỗng, trình biên dịch Kotlin sẽ tự cho đó là loại không rỗng
- Thay đổi loại biến
favoriteActortừ loại dữ liệuStringthành loại dữ liệuString?:
fun main() {
var favoriteActor: String? = "Sandra Oh"
favoriteActor = null
}
- In biến
favoriteActortrước và sau khi chỉ định lạinull, rồi chạy lập trình này:
fun main() {
var favoriteActor: String? = "Sandra Oh"
println(favoriteActor)
favoriteActor = null
println(favoriteActor)
}
Kết quả sẽ có dạng như đoạn mã sau:
Sandra Oh
null
Biến favoriteActor ban đầu đã giữ lại một chuỗi và sau đó nó được chuyển đổi thành null.
Thử nào
Bây giờ, bạn đã có thể sử dụng loại String? rỗng, bạn có thể khởi tạo biến có giá trị Int và chỉ định lại biến đó thành null hay không?
Viết một giá trị Int rỗng
- Xóa tất cả mã trong hàm
main():
fun main() {
}
- Tạo biến
numberthuộc loạiIntrỗng rồi chỉ định giá trị10cho biến đó:
fun main() {
var number: Int? = 10
}
- In biến
numberrồi chạy lập trình:
fun main() {
var number: Int? = 10
println(number)
}
Kết quả như mong đợi:
10
- Chỉ định lại biến
numberchonullđể xác nhận biến đó là rỗng:
fun main() {
var number: Int? = 10
println(number)
number = null
}
- Thêm một câu lệnh
println(number)khác làm dòng lệnh cuối của lập trình rồi chạy lập trình đó:
fun main() {
var number: Int? = 10
println(number)
number = null
println(number)
}
Kết quả như mong đợi:
10
null
Lưu ý: Mặc dù nên sử dụng biến rỗng cho các biến có thể có giá trị null, nhưng bạn nên sử dụng biến không rỗng cho các biến không bao giờ được có giá trị null vì việc truy cập vào các biến rỗng có thể cần nhiều thao tác xử lý phức tạp hơn. Bạn tìm hiểu về các kỹ thuật khác nhau để xử lý các biến rỗng trong phần tiếp theo.
Xử lý các biến có thuộc tính rỗng
Trước đây, bạn đã học cách dùng toán tử . để truy cập vào các phương thức và thuộc tính của biến không rỗng. Trong phần này, bạn sẽ tìm hiểu cách sử dụng nó để truy cập vào các phương thức và thuộc tính của biến rỗng.
Để truy cập vào một thuộc tính của biến favoriteActor không rỗng, hãy làm theo các bước sau:
- Xóa toàn bộ mã trong hàm
main()rồi khai báo một biếnfavoriteActorthuộc loạiStringvà chỉ định nó cho tên của diễn viên bạn yêu thích:
fun main() {
var favoriteActor: String = "Sandra Oh"
}
- In số lượng ký tự trong giá trị biến
favoriteActorbằng thuộc tínhlengthrồi chạy chương trình này:
fun main() {
var favoriteActor: String = "Sandra Oh"
println(favoriteActor.length)
}
Kết quả như mong đợi:
9
Có 9 ký tự trong giá trị của biến favoriteActor, bao gồm cả dấu cách. Số lượng ký tự của tên diễn viên bạn yêu thích có thể khác.
Truy cập vào một thuộc tính của một biến rỗng
Hãy tưởng tượng bạn muốn đặt biến favoriteActor thành rỗng để những người không có diễn viên yêu thích nào có thể chỉ định biến đó cho null.
Để truy cập vào một thuộc tính của biến favoriteActor rỗng, hãy làm theo các bước sau:
- Hãy thay đổi loại biến
favoriteActorthành loại giá trị rỗng rồi chạy lập trình này:
fun main() {
var favoriteActor: String? = "Sandra Oh"
println(favoriteActor.length)
}
Bạn sẽ nhận được thông báo lỗi sau:

Lỗi này là một lỗi biên dịch. Như đã đề cập trong một lớp học lập trình trước, lỗi biên dịch xảy ra khi Kotlin không thể biên dịch mã do lỗi cú pháp trong mã.
Kotlin có chủ ý áp dụng các quy tắc cú pháp để có thể đạt được độ an toàn null, nghĩa là đảm bảo không có lệnh gọi do nhầm lẫn nào được thực hiện trên các biếnnull. Điều này không có nghĩa là các biến không thể null. Nó có nghĩa là nếu thành viên của một biến được truy cập, thì biến đó không thể là null.
Điều này rất quan trọng vì nếu có sự cố khi truy cập vào một phần của biến null – còn gọi lànull tham chiếu – khi ứng dụng đang chạy, ứng dụng sẽ gặp sự cố do biến null không chứa bất kỳ thuộc tính hoặc phương thức nào. Loại sự cố này được gọi là lỗi thời gian chạy, trong đó lỗi xảy ra sau khi mã đã biên dịch và chạy.
Do tính chất an toàn null trong Kotlin, các lỗi thời gian chạy này sẽ bị ngăn chặn do trình biên dịch Kotlin buộcnull kiểm tra đối với các loại rỗng. kiểm tra Null là quá trình kiểm tra xem một biến có thể là null hay không trước khi được truy cập và xử lý dưới dạng giá trị rỗng. Nếu muốn sử dụng một giá trị rỗng cho loại không có giá trị rỗng, bạn cần phải xác định rõ ràng giá trị của null. Bạn có thể tìm hiểu về vấn đề này trong phần Sử dụng câu lệnh có điều kiện if/else trong phần sau của học lập trình này.
Trong ví dụ này, mã không thành công tại thời điểm biên dịch vì nó không được phép tham chiếu trực tiếp đến thuộc tính length cho biến favoriteActor vì có khả năng biến là null.
Tiếp theo, bạn sẽ tìm hiểu các kỹ thuật và toán tử để làm việc với các loại rỗng.
Dùng toán tử an toàn cho lệnh gọi của ?.
Bạn có thể dùng toán tử an toàn cho lệnh gọi ?. để truy cập vào các phương thức hoặc thuộc tính của biến rỗng.

Để sử dụng toán tử an toàn cho lệnh gọi ?. nhằm truy cập vào một phương thức hoặc thuộc tính, hãy thêm biểu tượng ? vào sau tên biến và truy cập vào phương thức hoặc thuộc tính có ký hiệu ..
Toán tử an toàn cho lệnh gọi ?. cho phép việc truy cập an toàn hơn vào các biến rỗng vì trình biên dịch Kotlin dừng mọi hoạt động truy cập của thành viên vào các tham chiếu null và trả null về cho thành viên được quyền truy cập.
Để truy cập an toàn vào một thuộc tính của biến favoriteActor rỗng, hãy làm theo các bước sau:
- Trong câu lệnh
println(), hãy thay thế toán tử.bằng toán tử an toàn cho lệnh gọi?.:
fun main() {
var favoriteActor: String? = "Sandra Oh"
println(favoriteActor?.length)
}
- Chạy lập trình này rồi xác minh kết quả đúng như mong đợi:
9
Số lượng ký tự của tên diễn viên yêu thích có thể khác nhau.
- Chỉ định lại biến
favoriteActorchonullrồi chạy lập trình này:
fun main() {
var favoriteActor: String? = null
println(favoriteActor?.length)
}
Bạn sẽ đạt được kết quả như sau:
null
Xin lưu ý rằng chương trình này sẽ không gặp sự cố mặc dù đã cố gắng truy cập vào thuộc tính length của một biến null. Biểu thức an toàn cho lệnh gọi trở về null.
Lưu ý: Bạn cũng có thể sử dụng toán tử an toàn cho lệnh gọi ?. trên các biến không rỗng để truy cập vào một phương thức hoặc thuộc tính. Mặc dù trình biên dịch Kotlin sẽ không báo lỗi, nhưng điều đó là không cần thiết vì việc truy cập vào các phương thức hoặc thuộc tính cho biến không rỗng luôn an toàn.
Dùng toán tử xác nhận không rỗng !!
Bạn cũng có thể dùng toán tử xác nhận không rỗng !! để truy cập vào các phương thức hoặc thuộc tính của biến rỗng.

Sau biến rỗng, bạn cần thêm toán tử xác nhận không rỗng !! theo sau là toán tử ., sau đó là phương thức hoặc thuộc tính không có khoảng trắng.
Dựa vào tên cho ta thấy, nếu bạn sử dụng toán tử xác nhận không rỗng !!, điều đó có nghĩa là bạn xác nhận giá trị của biến không null, bất kể nó có hay không.
Không giống như toán tử an toàn cho lệnh gọi ?., việc sử dụng toán tử xác nhận không rỗng !! có thể dẫn đến lỗi NullPointerException nếu biến rỗng thực sự là null. Do đó, chỉ nên thực hiện khi biến luôn có giá trị không rỗng hoặc một xử lý ngoại lệ thích hợp đã được thiết lập. Khi không được xử lý, các trường hợp ngoại lệ có thể gây ra lỗi thời gian chạy. Bạn sẽ tìm hiểu về cách xử lý ngoại lệ trong các bài sau của khóa học.
Để truy cập vào một thuộc tính của biếnfavoriteActor biến bằng toán tử xác nhận không rỗng !!, hãy làm theo các bước sau:
- Chỉ định lại biến
favoriteActorcho tên của diễn viên bạn yêu thích rồi thay thế toán tử an toàn cho lệnh gọi?.bằng toán tử xác nhận không rỗng!!trong câu lệnhprintln():
fun main() {
var favoriteActor: String? = "Sandra Oh"
println(favoriteActor!!.length)
}
- Chạy lập trình này rồi xác minh kết quả đúng như mong đợi:
9
Số lượng ký tự của tên diễn viên yêu thích có thể khác nhau.
- Chỉ định lại biến
favoriteActorchonullrồi chạy lập trình này:
fun main() {
var favoriteActor: String? = null
println(favoriteActor!!.length)
}
Bạn gặp phải lỗi NullPointerException:

Lỗi Kotlin này cho thấy lập trình của bạn đã gặp sự cố trong quá trình thực thi. Do đó, bạn không nên dùng toán tử xác nhận không rỗng !! trừ khi bạn chắc chắn biến đó không null.
Lưu ý: Trong các ngôn ngữ lập trình khác không chứa thuộc tính kiểm tra an toàn của giá trị rỗng, lỗi NullPointerException là nguyên nhân phổ biến gây ra các sự cố ứng dụng. Do đó, Kotlin loại bỏ nguyên nhân chủ yếu gây ra sự cố cho chương trình vì nó bao gồm tính an toàn null trong ngôn ngữ đó.
Sử dụng câu lệnh có điều kiện if/else
Bạn có thể sử dụng nhánh if trong câu lệnh có điều kiện if/else để thực hiện kiểm tra null.

Để thực hiện kiểm tra null, bạn có thể kiểm tra để đảm bảo biến rỗng không bằng null với toán tử so sánh !=.
Câu lệnh if/else
Bạn có thể sử dụng câu lệnh if/else cùng với việc kiểm tra null như sau:

Bước kiểm tra tính rỗng rất hữu ích khi kết hợp với câu lệnh if/else:
- Bước kiểm tra
nullcủa biểu thứcnullableVariable != nullđược dùng làm câu lệnh điều kiệnif. - Body 1 (nội dung 1) bên trong nhánh
ifgiả định biến không có giá trị rỗng. Do đó, trong phần nội dung này, bạn có thể tự do truy cập vào các phương thức hoặc thuộc tính của biến như là biến không rỗng khi không cần dùng toán tử an toàn cho lệnh gọi?.hoặc toán tử xác nhận không rỗng!!. - Body 2 (Thân 2) bên trong nhánh
elsegiả định biến đó lànull. Do đó, trong phần nội dung này, bạn có thể thêm câu lệnh sẽ chạy khi biến lànull. Nhánhelselà không bắt buộc. Bạn chỉ có thể sử dụng câu lệnh có điều kiệnifđể chạy kiểm tranullmà không phải cung cấp thao tác mặc định khi bước kiểm tranullkhông thành công.
Việc kiểm tra null thuận tiện hơn với câu lệnh điều kiện if khi có nhiều dòng mã sử dụng biến rỗng. Ngược lại, toán tử an toàn cho lệnh gọi ?. thuận tiện hơn cho việc tham chiếu duy nhất biến có tính rỗng.
Để viết một câu lệnh if/else có kiểm tra tính null cho biến favoriteActor, hãy làm theo các bước sau:
- Chỉ định lại biến
favoriteActortheo tên của diễn viên bạn yêu thích rồi xóa câu lệnhprintln():
fun main() {
var favoriteActor: String? = "Sandra Oh"
}
- Thêm một nhánh
ifcó mộ câu lệnh điều kiệnfavoriteActor != null:
fun main() {
var favoriteActor: String? = "Sandra Oh"
if (favoriteActor != null) {
}
}
- Trong phần nội dung của nhánh
if, hãy thêm một câu lệnhprintlnchấp nhận chuỗi"The number of characters in your favorite actor's name is ${favoriteActor.length}"rồi chạy lập trình:
fun main() {
var favoriteActor: String? = "Sandra Oh"
if (favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
}
}
Kết quả như mong đợi.
The number of characters in your favorite actor's name is 9.
Số lượng ký tự của tên diễn viên bạn yêu thích có thể khác.
Xin lưu ý bạn có thể truy cập vào phương thức độ dài của tên trực tiếp với toán tử . vì bạn sẽ truy cập vào phương thức length bên trong nhánh if sau quá trình kiểm tra null. Như thế, trình biên dịch Kotlin sẽ biết không có khả năng biến favoriteActor là null, vì vậy nó cho phép truy cập trực tiếp vào thuộc tính.
- Không bắt buộc: Thêm nhánh
elseđể xử lý trường hợp tên của diễn viên lànull:
fun main() {
var favoriteActor: String? = "Sandra Oh"
if (favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
} else {
}
}
- Trong phần nội dung của nhánh
else, hãy thêm một câu lệnhprintlnsẽ nhận chuỗi"You didn't input a name.":
fun main() {
var favoriteActor: String? = "Sandra Oh"
if (favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
} else {
println("You didn't input a name.")
}
}
- Chỉ định biến
favoriteActorchonullrồi chạy lập trình:
fun main() {
var favoriteActor: String? = null
if(favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
} else {
println("You didn't input a name.")
}
}
Kết quả như mong đợi:
You didn't input a name.
if/else biểu thức
Bạn cũng có thể kết hợp việc kiểm tra null với biểu thức if/else để chuyển đổi một biến rỗng thành một biến không có giá trị rỗng.

Cách chỉ định biểu thức if/else cho một loại không rỗng:
- Bước kiểm tra
nullableVariable != nullnullđược sử dụng làm câu lệnh điều kiệnif. - Body 1 (nội dung 1) bên trong nhánh
ifgiả định biến không có giá trị rỗng. Do đó, trong phần nội dung này, bạn có thể truy cập vào các phương thức hoặc thuộc tính của biến như đó là biến không rỗng nếu không có toán tử an toàn?.hoặc toán tử xác nhận không rỗng.!!. - Body 2 (Thân 2) bên trong nhánh
elsegiả định biến đó lànull. Do đó, trong phần nội dung này, bạn có thể thêm câu lệnh sẽ chạy khi biến lànull. - Trong dòng lệnh cuối cùng của nội dung 1 và 2, bạn cần sử dụng một biểu thức hoặc giá trị dẫn đến loại không rỗng để nó được gán cho biến không rỗng khi bước kiểm tra
nullđạt hoặc không.
Để sử dụng biểu thức if/else nhằm viết lại chương trình để biểu thức này chỉ có thể sử dụng một câu lệnh println, hãy làm theo các bước sau:
- Chỉ định biến
favoriteActorcho tên của diễn viên bạn yêu thích:
fun main() {
var favoriteActor: String? = "Sandra Oh"
if (favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
} else {
println("You didn't input a name.")
}
}
- Tạo biến
lengthOfNamerồi chỉ định biến đó cho biểu thứcif/else:
fun main() {
var favoriteActor: String? = "Sandra Oh"
val lengthOfName = if(favoriteActor != null) {
println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
} else {
println("You didn't input a name.")
}
}
- Xóa cả hai câu lệnh
println()khỏi nhánhifvàelse:
fun main() {
var favoriteActor: String? = "Sandra Oh"
val lengthOfName = if(favoriteActor != null) {
} else {
}
}
- Trong phần nội dung của nhánh
if, hãy thêm biểu thứcfavoriteActor.length:
fun main() {
val favoriteActor: String? = "Sandra Oh"
val lengthOfName = if(favoriteActor != null) {
favoriteActor.length
} else {
}
}
Thuộc tính length của biến favoriteActor được truy cập trực tiếp bằng toán tử ..
- Trong phần nội dung của nhánh
else, hãy thêm một giá trị0:
fun main() {
val favoriteActor: String? = "Sandra Oh"
val lengthOfName = if(favoriteActor != null) {
favoriteActor.length
} else {
0
}
}
Giá trị 0 đóng vai trò là giá trị mặc định khi tên là null.
- Ở cuối hàm
main(), hãy thêm một câu lệnhprintlnsẽ nhận chuỗi"The number of characters in your favorite actor's name is $lengthOfName."rồi chạy chương trình này:
fun main() {
val favoriteActor: String? = "Sandra Oh"
val lengthOfName = if(favoriteActor != null) {
favoriteActor.length
} else {
0
}
println("The number of characters in your favorite actor's name is $lengthOfName.")
}
Kết quả như mong đợi:
The number of characters in your favorite actor's name is 9.
Số lượng ký tự của tên bạn đã sử dụng có thể khác.
Lưu ý: Bạn cũng có thể dùng toán tử so sánh == để kiểm tra null thay vì toán tử !=. Khi thực hiện theo đó, hãy lưu ý hai phần nội dung này được đảo ngược. Phần nội dung của nhánh if giả định biến này là null và phần nội dung của nhánh else giả định biến đó không rỗng.
Sử dụng toán tử Elvis ?:
Toán tử Elvis ?: là toán tử bạn có thể sử dụng cùng với toán tử an toàn cho lệnh gọi ?.. Với toán tử Elvis ?:, bạn có thể thêm một giá trị mặc định khi toán tử an toàn cho lệnh gọi ?. trả về null. Biểu thức này tương tự như biểu thức if/else, nhưng theo cách đặc trưng hơn.
Nếu biến không phải là null, biểu thức trước toán tử Elvis ?: sẽ thực thi. Nếu biến là null, biểu thức sau toán tử Elvis ?: sẽ thực thi.

Để sửa đổi lập trình trước nhằm sử dụng toán tử Elvis ?:, hãy làm theo các bước sau:
- Xóa biến có câu lệnh có điều kiện
if/elserồi đặt biếnlengthOfNamethành biếnfavoriteActorrỗng và dùng toán tử an toàn cho lệnh gọi?.để gọi thuộc tínhlength:
fun main() {
val favoriteActor: String? = "Sandra Oh"
val lengthOfName = favoriteActor?.length
println("The number of characters in your favorite actor's name is $lengthOfName.")
}
- Sau thuộc tính
length, hãy thêm toán tử Elvis?:, theo sau là giá trị0, rồi chạy chương trình này:
fun main() {
val favoriteActor: String? = "Sandra Oh"
val lengthOfName = favoriteActor?.length ?: 0
println("The number of characters in your favorite actor's name is $lengthOfName.")
}
Kết quả vẫn như trước:
The number of characters in your favorite actor's name is 9.
Lưu ý: Toán tử Elvis ?: được đặt theo tên Elvis Presley, ngôi sao nhạc rock, vì nó giống với biểu tượng cảm xúc về mái tóc chải ngược trên trán của ông ấy khi nhìn nghiêng.