Backend

99 Ngày Java — Ngày 03: Biến & kiểu dữ liệu nguyên thủy

SSite Admin
31 tháng 07, 2026 5 phút đọc 265 lượt xem
99 Ngày Java — Ngày 03: Biến & kiểu dữ liệu nguyên thủy

Hai ngày đầu bạn đã chạy được chương trình và hiểu tường tận hàm main. Hôm nay lập trình thật sự bắt đầu: biến — chiếc hộp có tên để cất dữ liệu — và 8 kiểu dữ liệu nguyên thủy, những viên gạch nhỏ nhất mà mọi chương trình Java, từ Hello World đến hệ thống ngân hàng, đều xây lên từ đó.

Sketchnote Ngày 03: Biến và 8 kiểu dữ liệu nguyên thủy trong Java

Biến là gì?

Hãy hình dung bộ nhớ là một dãy tủ khóa. Biến là một ngăn tủ được đặt tên: bạn khai báo kiểu (ngăn to cỡ nào, đựng loại gì) và tên (nhãn dán ngoài cửa), rồi cất giá trị vào. Java là ngôn ngữ kiểu tĩnh (statically typed) — mỗi biến phải khai báo kiểu ngay từ đầu và giữ nguyên kiểu đó suốt đời, khác với Python hay JavaScript.

int age = 25;              // khai báo + khởi tạo một dòngdouble price = 19.99;
boolean isActive = true;

int score;                 // khai báo trước...
score = 90;                // ...gán giá trị sau

Quy tắc đặt tên: bắt đầu bằng chữ cái (không phải số), phân biệt hoa thường, và theo quy ước camelCasestudentCount chứ không phải student_count hay StudentCount. Tên biến nên nói rõ nó chứa gì: age tốt hơn a gấp nhiều lần khi đọc lại code sau một tuần.

8 kiểu dữ liệu nguyên thủy

Java có đúng 8 kiểu nguyên thủy (primitive types) — học thuộc hôm nay, dùng cả sự nghiệp. Chia làm 4 nhóm: số nguyên (byte, short, int, long), số thực (float, double), ký tự (char) và logic (boolean):

byte    b  = 127;              // 1 byte  : -128 → 127short   s  = 32_000;           // 2 bytes : ±32,767int     i  = 2_000_000_000;    // 4 bytes : ±2,1 tỷ — mặc định cho số nguyênlong    l  = 9_000_000_000L;   // 8 bytes : cần hậu tố Lfloat   f  = 3.14f;            // 4 bytes : cần hậu tố fdouble  d  = 3.14159265358979; // 8 bytes : mặc định cho số thựcchar    c  = 'J';              // 2 bytes : MỘT ký tự UTF-16, nháy đơnboolean ok = true;             // true / false
  • Dấu gạch dưới _ trong literal số (2_000_000_000) chỉ để dễ đọc — compiler bỏ qua hoàn toàn.

  • Số nguyên viết thẳng (9_000_000_000) mặc định là int — vượt phạm vi int là lỗi compile, nên literal long cần hậu tố L.

  • Số thực viết thẳng (3.14) mặc định là double — muốn float phải thêm f, nếu không compiler báo "possible lossy conversion".

  • char dùng nháy đơn cho một ký tự ('J'); nháy kép là String — không phải kiểu nguyên thủy, hẹn Ngày 09.

Vì sao gọi là "nguyên thủy"? Vì chúng không phải object: giá trị nằm trực tiếp trong biến, không có method nào để gọi, nhờ vậy cực nhanh và gọn. Mỗi kiểu có phiên bản wrapper object tương ứng (Integer, Double…) — chuyện của Ngày 22.

Giá trị mặc định — field có, biến local không

Đây là điểm hay bị hỏi khi phỏng vấn: field (biến khai báo trong class) được JVM tự gán giá trị mặc định — số về 0, boolean về false, char về '\u0000'. Nhưng biến local (khai báo trong method) thì không có mặc định — dùng khi chưa khởi tạo là compiler chặn ngay:

public class Defaults {
    static int counter;      // field: tự nhận 0
    static boolean flag;     // field: tự nhận false

    public static void main(String[] args) {
        System.out.println(counter); // 0
        System.out.println(flag);    // false

        int local;
        // System.out.println(local); // ❌ KHÔNG compile: biến local
        //                            //    chưa được khởi tạo
    }
}

Compiler khó tính ở đây là để cứu bạn: một biến "quên khởi tạo" trong C có thể mang giá trị rác ngẫu nhiên và gây bug ma quái — Java chọn cách từ chối biên dịch ngay từ đầu.

Overflow — khi chiếc hộp tràn

Mỗi kiểu có phạm vi hữu hạn. int dùng 4 byte nên chỉ đếm được tới 2_147_483_647 (Integer.MAX_VALUE). Cộng thêm 1? Java không báo lỗi — giá trị lặng lẽ quay vòng về số âm nhỏ nhất, như đồng hồ công-tơ-mét quay hết vòng:

int max = Integer.MAX_VALUE;       // 2_147_483_647
System.out.println(max + 1);       // -2147483648 — quay vòng về âm!

long safe = (long) max + 1;        // 2147483648 — ép sang long TRƯỚC khi cộng
System.out.println(safe);

Math.addExact(max, 1);             // ném ArithmeticException — sai thì báo,
                                   // không sai lặng lẽ

Overflow từng gây sự cố thật: YouTube phải nâng bộ đếm view của Gangnam Style lên long khi video vượt 2,1 tỷ lượt xem. Bài học: đại lượng có thể lớn (view, tiền theo đơn vị nhỏ nhất, timestamp) — dùng long ngay từ đầu; phép tính nhạy cảm — dùng Math.addExact để sai là ném exception thay vì sai lặng lẽ.

Chọn kiểu nào cho đúng?

  • Số nguyên: cứ int mà dùng — nhanh, đủ cho hầu hết trường hợp. Chỉ lên long khi giá trị có thể vượt 2,1 tỷ.

  • Số thực: mặc định doublefloat gần như chỉ còn trong đồ họa/mảng lớn cần tiết kiệm bộ nhớ.

  • Tiền tệ: đừng dùng float/double! Số thực nhị phân không biểu diễn chính xác 0.1 — Ngày 27 ta học BigDecimal cho việc này.

  • byte/short hiếm khi cần — chủ yếu khi làm việc với file nhị phân, mạng, hoặc mảng rất lớn.

  • boolean cho mọi cờ trạng thái — đặt tên dạng khẳng định: isActive, hasError.

Bài tập nhỏ

  • Khai báo đủ 8 biến cho 8 kiểu nguyên thủy, in từng biến ra màn hình.

  • In Integer.MAX_VALUE + 1Integer.MIN_VALUE - 1 — quan sát chiều quay vòng của overflow.

  • Thử gán int big = 3_000_000_000; rồi đọc kỹ thông báo lỗi của compiler — sửa bằng cách nào?

  • In 0.1 + 0.2 và giải thích vì sao kết quả không phải 0.3 — gợi ý cho Ngày 27.

Kết luận

Bạn đã biết biến là gì, thuộc mặt 8 kiểu nguyên thủy, hiểu vì sao biến local phải khởi tạo trước khi dùng và overflow nguy hiểm ra sao. Ngày 04, ta cho những chiếc hộp này "nói chuyện" với nhau bằng toán tử và biểu thức — cộng trừ nhân chia, so sánh, logic và cả toán tử 3 ngôi bí ẩn. Hẹn gặp lại!

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Java — Ngày 58: Optional

Optional là công cụ cho kiểu trả về — không field, không tham số, không bọc collection; chuỗi map/flatMap/filter thay kim tự tháp if; orElse luôn tính tham số còn orElseGet lười, orElseThrow cho “không có là lỗi” — và các anti-pattern isPresent + get, orElse(null).

23 thg 9, 20269 phút9
99 Ngày Spring — Ngày 58: Spring Boot Actuator

Boot 3 mặc định chỉ lộ health; bản đồ endpoint an toàn và nguy hiểm; HealthIndicator tự viết với liveness tách khỏi readiness cho Kubernetes, info từ build và git, metrics Micrometer với tag hữu hạn — và ba lớp khóa: cổng riêng, SecurityFilterChain với EndpointRequest, exclude env/heapdump/threaddump.

23 thg 9, 202610 phút5
So sánh EasyExcel và Apache Fesod: khác biệt thật nằm ở đâu?

Fesod là hậu duệ của EasyExcel, cùng engine SAX/SXSSF. Khác biệt kiểm chứng được: vòng đời dự án, POI 5.2.5 vs 5.5.1, các API mới (numRows, csv(), headerMergeStrategy) và độ bền với file xấu — không phải hiệu năng gấp nhiều lần.

23 thg 9, 20268 phút1