Optional / Nullable — các khái niệm chính và làm việc với kiểu nullable

Tác giả: IT Sectr Đã đăng: 2026-05-26 Thời gian đọc: 8 phút

Optional / Nullable — cơ chế của ngôn ngữ Swift và Kotlin để làm việc an toàn với sự thiếu vắng giá trị. Optional trong Swift và kiểu nullable trong Kotlin giải quyết cùng một vấn đề — null reference — nhưng với các cách tiếp cận cú pháp và ngữ nghĩa khác nhau. Theo Swift.org, 2026, các kiểu tùy chọn loại bỏ toàn bộ một lớp lỗi liên quan đến nil, chuyển việc kiểm tra null sang giai đoạn biên dịch.

Những điểm chính

  • Optional — kiểu Swift được biểu diễn dưới dạng enum với hai trường hợp: some(Value) và none.
  • Nullable — trong Kotlin được ký hiệu bằng dấu hỏi sau kiểu (String?), và gọi an toàn qua ?.
  • An toàn kiểu — cả hai cơ chế đảm bảo rằng giá trị null được xử lý một cách tường minh tại thời điểm biên dịch.
  • Unwrapping — Swift sử dụng if let, guard let và force unwrap (!). Kotlin sử dụng ?., !! và toán tử Elvis ?:.
  • Interop — Kotlin và Swift tương tác với cơ sở mã nullable thông qua chú thích và các kiểu đặc biệt (Implicitly Unwrapped Optional).

Optional và Nullable là gì?

Optional trong Swift và nullable trong Kotlin là các công cụ ngôn ngữ làm cho null trở thành một phần rõ ràng của hệ thống kiểu. Trong Swift, Optional là một enum: Optional.none (nil) và Optional.some(Wrapped). Trong Kotlin, nullable được ký hiệu bằng hậu tố ? trong kiểu: String? có thể là một chuỗi hoặc null.

Cả hai cách tiếp cận giải quyết vấn đề cơ bản mà Tony Hoare gọi là “sai lầm tỷ đô” — null reference. Trước khi có các kiểu tùy chọn, bất kỳ tham chiếu nào cũng có thể là null và việc kiểm tra được để cho nhà phát triển. Swift và Kotlin chuyển việc kiểm tra này sang giai đoạn biên dịch: mã bỏ qua null sẽ không được biên dịch.

Mặc dù có mục tiêu chung, Swift và Kotlin triển khai null-safety theo những cách khác nhau. Swift sử dụng kiểu đại số Optional với pattern-matching đầy đủ. Kotlin nhúng nullable vào hệ thống kiểu ở cấp độ trình biên dịch mà không tạo kiểu bao bọc riêng biệt.

Về mặt lịch sử, null reference xuất hiện vào năm 1965 trong ngôn ngữ ALGOL W như một cách để biểu diễn sự thiếu vắng giá trị. Qua sáu thập kỷ, null đã trở thành nguồn gốc của vô số sự cố — theo nghiên cứu của Tony Hoare, 30 đến 50 phần trăm lỗi trong mã sản xuất có liên quan đến NullPointerException. Swift với Optional và Kotlin với kiểu nullable đã trở thành những ngôn ngữ chính thống đầu tiên giải quyết vấn đề này ở cấp độ hệ thống kiểu, biến null thành một phần rõ ràng của hợp đồng hàm.

Optional trong Swift: cú pháp và làm việc với kiểu tùy chọn

Trong Swift, Optional là một kiểu hoàn chỉnh được khai báo là enum Optional<Wrapped>. Cú pháp đường ? thay thế ký hiệu đầy đủ: Int? tương đương với Optional<Int>. Làm việc với Optional bao gồm một số cách để trích xuất giá trị.

Ràng buộc if-let và guard-let

if let — trích xuất có điều kiện: nếu Optional chứa giá trị, nó được gắn với một hằng số trong khối. guard let — thoát sớm khỏi hàm nếu Optional là nil. guard let giữ mã phẳng, tránh các if-let lồng nhau.

Optional chaining

Optional chaining (truy cập an toàn tuần tự) qua ? cho phép gọi phương thức hoặc thuộc tính trên Optional mà không cần unwrapping tường minh. Nếu bất kỳ mắt xích nào trong chuỗi là nil, toàn bộ chuỗi trả về nil. Điều này giảm mã khi làm việc với dữ liệu phân cấp.

Toán tử nil-coalescing

?? (nil-coalescing) — toán tử trả về giá trị Optional nếu nó không nil, nếu không thì trả về giá trị mặc định. Đây là một thay thế ngắn gọn cho if-let để cung cấp giá trị dự phòng.

swift
var name: String? = "Alice"

// Ràng buộc If-let
if let unwrapped = name {
    print("Xin chào, \(unwrapped)")
}

// Optional chaining
let count = name?.count

// Nil-coalescing
let display = name ?? "Khách"

// Map trên Optional
let greeting = name.map { "Hello, \($0)" }

Nullable trong Kotlin: gọi an toàn và toán tử Elvis

Trong Kotlin, nullable là một phần của hệ thống kiểu, không phải kiểu bao bọc riêng biệt. Kiểu String? có thể chứa null, trong khi String (không có dấu hỏi) thì không bao giờ. Trình biên dịch theo dõi nullable thông qua smart cast và chú thích.

Gọi an toàn ?.

?. — toán tử gọi an toàn. Nếu đối tượng không null, phương thức hoặc thuộc tính được gọi; nếu null — null được trả về mà không gọi. Điều này tương tự như optional chaining trong Swift, nhưng cú pháp ngắn hơn.

Toán tử Elvis ?:

?: — phiên bản Kotlin của nil-coalescing. Nếu biểu thức bên trái không null, nó được trả về; nếu không — giá trị bên phải. Toán tử Elvis thường được kết hợp với thoát sớm qua return hoặc throw.

Smart cast và toán tử !!

Smart cast — trình biên dịch Kotlin tự động chuyển nullable thành non-null sau khi kiểm tra null trong if hoặc when. !! — gọi cưỡng bức (force unwrap), ném NullPointerException khi null. Chỉ sử dụng !! khi null là một lỗi.

kotlin
val name: String? = "Alice"

// Gọi an toàn
val length = name?.length

// Toán tử Elvis
val display = name ?: "Khách"

// Smart cast sau kiểm tra
if (name != null) {
    println("Độ dài: ${name.length}")
}

// Let với lambda
name?.let { println("Xin chào, $it") }

// Force unwrap — chỉ khi chắc chắn
val forced = name!!

Optional so với Nullable: khác biệt chính trong cách tiếp cận

Mặc dù Swift và Kotlin giải quyết cùng một nhiệm vụ, cách tiếp cận null-safety của chúng khác nhau về cơ bản. Hiểu những khác biệt này rất quan trọng cho các nhà phát triển làm việc với cả hai nền tảng.

Biểu diễn trong hệ thống kiểu

Swift sử dụng enum Optional — một kiểu đại số tiêu chuẩn. Kotlin nhúng nullable ở cấp độ hệ thống kiểu của trình biên dịch mà không tạo đối tượng bao bọc. Điều này ảnh hưởng đến hiệu suất: Optional trong Swift là một đối tượng trên heap, trong khi nullable trong Kotlin là kiểm tra null không cấp phát.

Cú pháp và tính biểu cảm

Cú pháp Kotlin ngắn hơn nhờ các toán tử tích hợp ?., ?:, !!. Swift yêu cầu cú pháp rõ ràng hơn: if let, guard let, map trên Optional. Tuy nhiên, Swift cung cấp pattern-matching qua switch, mà Kotlin không hỗ trợ trực tiếp cho nullable.

Tình huốngSwiftKotlin
Khai báovar name: String?val name: String?
Gọi an toànname?.countname?.length
Giá trị mặc địnhname ?? “Khách”name ?: “Khách”
Trích xuất có điều kiệnif let x = namename?.let { x -> }
Force unwrapname!name!!

Mẫu null-safety trong phát triển di động

Trong phát triển di động, các mẫu tiêu chuẩn để làm việc với kiểu tùy chọn đã được hình thành, giúp giảm mã mẫu và tăng tính an toàn.

Map và flatMap trên Optional

Swift và Kotlin hỗ trợ mapflatMap cho Optional và nullable. Nếu có giá trị, một phép biến đổi được áp dụng; nếu null — null được trả về. Điều này loại bỏ các kiểm tra if-let lồng nhau.

Giá trị mặc định qua Elvis

Thay vì if-let + else, hãy sử dụng ?: hoặc ?? với giá trị mặc định. Điều này làm cho mã trở nên khai báo: “sử dụng X nếu có, nếu không thì Y” thay vì kiểm tra theo thủ tục.

Nullable trong Compose và SwiftUI

Trong Jetpack ComposeSwiftUI, các kiểu tùy chọn kiểm soát hiển thị: nếu trạng thái là null — ẩn thành phần, nếu không thì hiển thị. Điều này tuân theo nguyên tắc single source of truth.

kotlin
data class UserState(
    val name: String?,
    val email: String?
)

// Smart cast trong when với các biến thể khác nhau
fun greeting(state: UserState): String = when {
    state.name != null && state.email != null ->
        "${state.name} (${state.email})"
    state.name != null -> state.name
    else -> "Khách"
}

// Compose: hiển thị theo sự hiện diện
@Composable
fun UserProfile(name: String?) {
    name?.let {
        Text(text = it)
    } ?: Text(text = "Không có dữ liệu")
}

Để di chuyển mã Java hiện có sang Kotlin, nên sử dụng các chú thích @Nullable@NonNull từ gói androidx.annotation. Trình biên dịch Kotlin tôn trọng các chú thích này khi tương tác với Java, tự động làm cho các kiểu tương ứng trở thành nullable hoặc non-null. Di chuyển dần dần với chú thích rõ ràng an toàn hơn so với việc bật null-safety toàn cục trong dự án.

Lỗi phổ biến khi làm việc với Optional và Nullable

Null-safety giảm số lượng lỗi nhưng không loại bỏ hoàn toàn. Các nhà phát triển thường mắc những lỗi đặc trưng khi làm việc với kiểu tùy chọn.

  • Force unwrap không đảm bảo — name! hoặc name!! mà không chắc chắn giá trị không nil gây ra sự cố trong sản xuất. Kiểm tra null trước force unwrap.
  • If-let quá mức — if-let lồng nhau cho ba Optional trở lên tạo ra kim tự tháp hủy diệt. Sử dụng guard let hoặc flatMap.
  • Bỏ qua nil-coalescing — kiểm tra tường minh qua if-let với khối else có thể được thay thế bằng ?? hoặc ?:, giúp giảm mã và cải thiện khả năng đọc.
  • Nullable trong API công khai — nếu một hàm chấp nhận nullable, mỗi lần gọi đều yêu cầu kiểm tra. Ưu tiên non-null với giá trị mặc định hoặc nạp chồng.

Câu hỏi thường gặp

Kotlin Nullable khác Swift Optional như thế nào?

Swift Optional là enum với các trường hợp some và none, một đối tượng trên heap. Kotlin nullable là một chú thích trong hệ thống kiểu, được trình biên dịch kiểm tra mà không tạo wrapper. Kotlin cô đọng hơn về cú pháp, Swift mạnh hơn trong pattern-matching.

Có null-safety trong Java không?

Java không có null-safety tích hợp. Optional (Java 8+) tương tự Swift Optional, nhưng nó là một wrapper có chi phí. Các chú thích @Nullable@NonNull giúp các công cụ phân tích tĩnh nhưng không đảm bảo an toàn.

Khi nào sử dụng ?.let trong Kotlin thay vì if-let?

?.let thuận tiện cho chuỗi thao tác: áp dụng biến đổi, lưu vào cơ sở dữ liệu, cập nhật UI — tất cả trong một khối. if với kiểm tra null tốt hơn cho các điều kiện phức tạp với nhiều biến nullable.

Optional ảnh hưởng đến hiệu suất như thế nào?

Swift Optional là enum với lưu trữ gián tiếp cho các kiểu lớn, có thể gây cấp phát. Kotlin nullable là kiểm tra null không có chi phí bổ sung. Cho các đường dẫn nóng (recycler view, hoạt ảnh), Kotlin hiệu quả hơn.

Có nên sử dụng nullable cho trường của data class không?

Chỉ sử dụng nullable khi trường thực sự có thể vắng mặt: dữ liệu hồ sơ tùy chọn, cài đặt không bắt buộc. Nếu một trường luôn được điền, hãy sử dụng non-null với giá trị mặc định qua toán tử Elvis khi tạo.

Tóm tắt

  • Optional (Swift) và Nullable (Kotlin) là các cơ chế ngôn ngữ chuyển việc xử lý null sang thời gian biên dịch và ngăn chặn NPE.
  • Swift Optional là enum với hai trường hợp, cung cấp pattern-matching và map/flatMap. Kotlin nullable là một phần của hệ thống kiểu với các toán tử nhỏ gọn ?., ?:, !!.
  • Optional chaining (Swift ?.) và gọi an toàn (Kotlin ?.) cho phép làm việc với dữ liệu phân cấp mà không cần kiểm tra lồng nhau.
  • Nil-coalescing (??) và toán tử Elvis (?:) cung cấp giá trị mặc định mà không cần nhánh if-else tường minh.
  • Smart cast trong Kotlin tự động chuyển nullable thành non-null sau khi kiểm tra, giảm số lần chuyển đổi tường minh.
  • Tránh force unwrap (! / !!) trong sản xuất, if-let quá mức và kiểu nullable trong API công khai khi không cần thiết.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm