Skip to Content
Kotlin📘 Ngôn ngữ Kotlin🕵️ Kiểm tra và Ép kiểu

Type Checks and Casts (Kiểm tra và Ép kiểu)

🎯 Mục tiêu: Nắm vững cách kiểm tra kiểu (is), ép kiểu an toàn (as?) và cơ chế Smart Casts thông minh của Kotlin.


🕵️ Kiểm tra kiểu (is / !is)

Dùng is để kiểm tra xem một object có phải là kiểu cụ thể hay không (tương đương instanceof trong Java).

if (obj is String) { print(obj.length) } if (obj !is String) { // Tương đương !(obj is String) print("Not a String") }

🧠 Smart Casts

Kotlin compiler cực kỳ thông minh! Nếu bạn đã kiểm tra kiểu với is, nó sẽ tự động ép kiểu (cast) biến đó trong phạm vi tương ứng mà không cần bạn làm gì thêm.

Với ifwhen

fun demo(x: Any) { if (x is String) { print(x.length) // x tự động là String } } when (x) { is Int -> print(x + 1) is String -> print(x.length + 1) is IntArray -> print(x.sum()) }

Với &&||

// Bên phải && if (x is String && x.length > 0) { print(x.length) // x là String } // Bên phải || (negative check) if (x !is String || x.isEmpty()) { return }

Smart Casts hoạt động khi nào?

Smart cast chỉ hoạt động khi compiler đảm bảo biến không thay đổi giữa lúc kiểm tra và lúc sử dụng.

  • val local variables: Luôn hoạt động (trừ local delegated properties).
  • val properties: Hoạt động nếu private/internal hoặc check trong cùng module.
  • var local variables: Hoạt động nếu không bị thay đổi giữa check và use, không bị capture bởi lambda thay đổi nó.
  • var properties: Không bao giờ hoạt động (vì code khác có thể thay đổi bất cứ lúc nào).

🔄 Ép kiểu (Type Casts)

Unsafe Cast (as)

Dùng as khi bạn chắc chắn về kiểu. Nếu sai, nó sẽ ném ClassCastException.

val y = null val x: String = y as String // ❌ Exception: null cannot be cast to non-null String

Để cast nullable:

val x: String? = y as String? // ✅ OK, x = null

Safe Cast (as?)

Dùng as? để tránh exception. Nếu cast thất bại, nó trả về null.

val x: String? = y as? String

Đây là cách được khuyên dùng để xử lý ép kiểu an toàn.


🧬 Generics Type Checks

Do Type Erasure (xóa kiểu generic tại runtime), bạn không thể kiểm tra cụ thể generic type của một instance (trừ khi dùng inline reified).

// ❌ Lỗi biên dịch // if (list is List<String>) { ... } // ✅ OK: Kiểm tra Star-projected type if (list is List<*>) { // list là một List nào đó, nhưng không biết phần tử là gì }

Để kiểm tra generic type thực sự, dùng Inline Functions với reified:

inline fun <reified T> isType(value: Any): Boolean { return value is T }

🛠️ Thực hành

Bài tập 1: Xử lý Any

fun process(input: Any) { // TODO: // Nếu input là String, in độ dài // Nếu input là Int, in bình phương // Nếu input là List, in số phần tử // Dùng when expression }

Lời giải:

fun process(input: Any) { when (input) { is String -> println("String length: ${input.length}") is Int -> println("Square: ${input * input}") is List<*> -> println("List size: ${input.size}") else -> println("Unknown type") } }

✅ Checklist

  • Sử dụng is để kiểm tra kiểu
  • Tận dụng Smart Casts để code gọn hơn
  • Luôn ưu tiên as? thay vì as
  • Hiểu hạn chế của Smart Casts với var properties
Last updated on