object trong Kotlin: cú pháp và ứng dụng thực tế của đối tượng singleton

Tác giả: IT Sectr Đã đăng: 2026-06-21 Thời gian đọc: 9 phút

object trong Kotlin là cách khai báo để tạo một đối tượng singleton với khởi tạo lười biếng và an toàn luồng theo mặc định. Từ khóa object thay thế toàn bộ một lớp bằng một phiên bản duy nhất và được sử dụng để khai báo singleton, companion object, đối tượng ẩn danh và tiện ích tĩnh. Theo Tài liệu Kotlin của JetBrains (2026), object declaration là cách đơn giản và an toàn nhất để triển khai singleton trong thế giới JVM.

Những điểm chính

  • object — từ khóa khai báo lớp singleton với một phiên bản duy nhất
  • Khởi tạo lười biếng — object được tạo khi truy cập lần đầu, không phải khi tải lớp
  • Companion object — tương tự thành viên tĩnh trong Kotlin (không có từ khóa static)
  • Object expression — đối tượng ẩn danh để ghi đè phương thức ngay lập tức
  • An toàn luồng — khởi tạo object được đảm bảo thread-safe

Object trong Kotlin là gì?

object trong Kotlin là một hình thức khai báo đặc biệt đồng thời định nghĩa một lớp và tạo phiên bản duy nhất của nó (singleton). Nó là sự kết hợp giữa khai báo lớp và tạo phiên bản trong một cấu trúc duy nhất.

Trong Java, việc tạo singleton yêu cầu một hàm tạo riêng tư, một trường tĩnh, phương thức getInstance và xử lý an toàn luồng. Kotlin object thực hiện điều này bằng một dòng mã duy nhất: object MySingleton { }. Trình biên dịch tự động tạo khởi tạo lười biếng an toàn luồng bằng cách sử dụng cơ chế static initializer trong bytecode JVM.

Theo Đặc tả ngôn ngữ Kotlin (2026), object declaration được biên dịch thành một lớp final với hàm tạo riêng tư và trường tĩnh INSTANCE được khởi tạo trong khối tĩnh. Điều này đảm bảo tính nguyên tử của khởi tạo ở cấp độ JVM.

Đối tượng singleton (object declaration)

Object declaration (đối tượng singleton) được khai báo bằng từ khóa object theo sau là một tên. Phần thân của đối tượng có thể chứa thuộc tính, phương thức, khối init và kế thừa các lớp hoặc giao diện khác.

kotlin
object DatabaseManager {
    private val connection: String = "jdbc:postgresql://localhost:5432/app"
    
    fun query(sql: String): List<Map<String, Any>> {
        // đang thực thi truy vấn
        return emptyList()
    }
}

// Cách sử dụng
DatabaseManager.query("SELECT * FROM users")

Việc khởi tạo DatabaseManager xảy ra khi truy cập lần đầu — một cách lười biếng và an toàn luồng. Không cần mã đồng bộ hóa bổ sung.

Kế thừa cho object

Object có thể kế thừa các lớp và giao diện thông thường. Điều này cho phép sử dụng object như một triển khai của lớp trừu tượng hoặc giao diện với một phiên bản duy nhất.

kotlin
interface Logger {
    fun log(message: String)
}

object ConsoleLogger : Logger {
    override fun log(message: String) {
        println("[LOG] $message")
    }
}

Companion object

companion object là một object đặc biệt được khai báo bên trong một lớp với từ khóa companion. Nó thay thế các thành viên tĩnh trong Kotlin vì ngôn ngữ không có từ khóa static.

kotlin
class ApiClient {
    companion object {
        private const val BASE_URL = "https://api.example.com"
        
        fun create(): ApiClient {
            return ApiClient()
        }
    }
}

// Gọi mà không tạo phiên bản ApiClient
val client = ApiClient.create()

Companion object có thể có tên (mặc định là Companion), triển khai giao diện và được mở rộng thông qua extension functions. Không giống như phương thức tĩnh trong Java, companion object là một đối tượng đầy đủ có thể được truyền như đối số hoặc lưu trong biến.

Theo Thực hành tốt nhất Kotlin (2026), companion object được sử dụng cho phương thức factory, hằng số và tiện ích tĩnh liên quan đến lớp. Khuyến cáo tránh sử dụng companion object quá mức — đối với các tiện ích không liên quan, các hàm cấp cao nhất sẽ tốt hơn.

Chú thích @JvmStatic

Để tương thích với Java, các phương thức của companion object có thể được chú thích bằng @JvmStatic. Điều này tạo ra một phương thức tĩnh thực sự trong bytecode JVM, có thể truy cập từ mã Java mà không cần cú pháp Companion.

Object expressions (đối tượng ẩn danh)

Object expression là một đối tượng ẩn danh được tạo ngay tại chỗ để ghi đè phương thức của một lớp hoặc giao diện mà không cần khai báo một lớp có tên riêng biệt.

kotlin
val handler = object : Runnable {
    override fun run() {
        println("Nhiệm vụ đã được thực thi")
    }
}

thread(handler)

Object expressions khác với khai báo object ở chỗ chúng tạo một phiên bản mới mỗi lần thực thi. Chúng không phải là singleton và không có tên. Các đối tượng ẩn danh có thể capture biến từ bao đóng của chúng, giống như lambda.

Không giống như Java, nơi các lớp ẩn danh chỉ có thể kế thừa một kiểu, object expression của Kotlin có thể kế thừa nhiều kiểu cùng một lúc.

kotlin
interface Clickable {
    fun click()
}

abstract class View {
    abstract fun render()
}

val button = object : View(), Clickable {
    override fun render() = println("Đang hiển thị nút")
    override fun click() = println("Nút đã được nhấp")
}

Các tình huống sử dụng thực tế

Object là một trong những cấu trúc linh hoạt nhất của Kotlin, được sử dụng trong nhiều tình huống.

Singleton Repository

Trong các dự án Android, object thường được sử dụng để khai báo Repository khi không cần nhiều phiên bản. Một phiên bản duy nhất đảm bảo tính nhất quán dữ liệu.

kotlin
object UserRepository {
    fun getUser(id: Int): User? {
        // đang lấy người dùng
        return null
    }
}

Phương thức factory qua companion object

Companion object với phương thức factory là một giải pháp thay thế cho nhiều hàm tạo. Các phương thức factory có tên làm cho mã tự ghi chú.

kotlin
data class GsonParser {
    companion object {
        fun create(): GsonParser = GsonParser()
        fun createPretty(): GsonParser = GsonParser()
    }
}

Hằng số và kiểu liệt kê

Object có thể hoạt động như một vùng chứa hằng số, thay thế các trường static final trong Java. Object hỗ trợ kế thừa, cho phép tạo các hệ thống phân cấp cấu hình.

Theo Thư viện chuẩn Kotlin (2026), object declaration là cách hiệu quả nhất để tạo singleton trong Kotlin, vượt trội so với triển khai double-checked locking và tương đương với singleton enum trong Java.

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

Object khác với lớp thông thường như thế nào?

Object đồng thời khai báo một lớp và tạo phiên bản duy nhất của nó. Một lớp thông thường có thể có nhiều phiên bản được tạo qua hàm tạo.

Khi nào object declaration được khởi tạo?

Một cách lười biếng — khi truy cập lần đầu vào đối tượng. Cho đến lúc đó, không có bộ nhớ nào được cấp phát và mã trong khối init không được thực thi.

Object có thể có hàm tạo không?

Không, object không thể có hàm tạo rõ ràng. Việc khởi tạo được thực hiện trong khối init, được gọi một lần khi truy cập lần đầu vào đối tượng.

Companion object khác với object thông thường như thế nào?

companion object là một object được khai báo bên trong một lớp. Các thành viên của nó có thể truy cập qua tên lớp mà không cần tạo phiên bản, thay thế các thành viên tĩnh của Java.

Object declarations có an toàn trong môi trường đa luồng không?

Có, việc khởi tạo object hoàn toàn an toàn luồng nhờ bộ khởi tạo tĩnh của JVM. Không cần đồng bộ hóa bổ sung.

Tổng kết

  • object — singleton khai báo với khởi tạo lười biếng và an toàn luồng
  • companion object — thành viên tĩnh trong Kotlin, phương thức factory, hằng số
  • Object expression — đối tượng ẩn danh ngay tại chỗ với capture biến từ bao đóng
  • Kế thừa — object có thể kế thừa lớp và giao diện, bao gồm nhiều kiểu
  • Hiệu suất — khởi tạo qua static initializer của JVM, không có chi phí double-checked locking
  • Sử dụng — dịch vụ singleton, repository, hằng số, factory, bộ điều hợp listener
  • Giới hạn — không có hàm tạo rõ ràng, một phiên bản trên mỗi JVM

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