CodeGym /Các khóa học /JAVA 25 SELF /Suy luận kiểu tự động, hằng số trong Java

Suy luận kiểu tự động, hằng số trong Java

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Từ khóa var

Khi mới bắt đầu viết code Java, chúng ta gặp hệ thống kiểu nghiêm ngặt: mỗi biến cần được khai báo rõ ràng — phải chỉ ra kiểu của nó. Điều này hữu ích cho độ tin cậy, nhưng đôi khi câu lệnh trở nên cồng kềnh và làm nặng mã nguồn. Để làm cho mọi thứ dễ chịu hơn, Java đã bổ sung một công cụ tiện lợi — suy luận kiểu tự động (var).

var cho phép viết mã ngắn gọn và sạch hơn mà không hy sinh an toàn kiểu: bạn viết giá trị, còn trình biên dịch sẽ tự suy ra kiểu.

Ví dụ

var age = 23;            // trình biên dịch suy ra kiểu của số 23 và thay bằng int age
var name = "Anna";       // trình biên dịch suy ra kiểu của "Anna" và thay bằng String name
var price = 99.99;       // trình biên dịch suy ra kiểu của 99.99 và thay bằng double price

Tại sao var xuất hiện?

  • Dễ đọc: không cần tự tay viết các kiểu dài (như HashMap<String, List<Integer>>).
  • Linh hoạt: giúp dễ đổi kiểu trong tương lai: sửa ở vế phải — vế trái var sẽ tự điều chỉnh.
  • Phong cách hiện đại: hầu hết các dự án Java hiện đại dùng var ở nơi kiểu có thể đọc ra dễ dàng từ biểu thức khởi tạo.

Khi nào có thể (và nên) dùng var

  • Khi từ vế phải có thể thấy rõ kiểu của biến là gì.
  • Khi kiểu là hiển nhiên (var price = 100; — rõ ràng đây là int).
  • Khi kiểu quá dài hoặc phức tạp (ví dụ, HashMap<Integer, List<Calendar>>).

Ví dụ với mảng

var numbers = new int[] { 1, 2, 3, 4 };

Ví dụ với phương thức

var input = console.nextLine(); // input là String (phương thức trả về String)

Khi tốt hơn là KHÔNG dùng var

Nếu kiểu không rõ ràng từ vế phải, mã có thể trở nên kém dễ hiểu. Nếu sau một tháng chính bạn cũng không nhớ kiểu là gì, hãy chỉ rõ kiểu tường minh.

var mystery = DoSomethingVeryComplicated(); // BẠN LÀ AI, mystery???

Ở đây tốt hơn là chỉ rõ kiểu:

String result = DoSomethingVeryComplicated();

Quy tắc vàng: chỉ dùng var ở nơi nó không làm giảm tính dễ đọc!

var — chỉ cho biến cục bộ

Từ khóa var chỉ hoạt động cho biến cục bộ — bên trong phương thức. Không thể dùng var cho:

  • tham số phương thức;
  • trường (field) của lớp;
  • hằng số.

var hoạt động “bên dưới nắp” như thế nào

  • Trình biên dịch Java sẽ thay thế bằng kiểu đúng tại thời điểm biên dịch.
  • Sau khi biên dịch thì không còn var nữa.
  • Không mất hiệu năng: đây chỉ là tiện ích cho lập trình viên.
var year = 2025; // tại giai đoạn biên dịch trở thành: int year = 2025;

Các lỗi thường gặp khi dùng var

Biến chưa được khởi tạo:

var a; // LỖI: Trình biên dịch không có cơ sở để suy ra kiểu!

Khởi tạo mơ hồ:

var list = null; // LỖI: Không thể xác định kiểu từ null!

Tái sử dụng biến với các kiểu khác nhau:

var value = 5;     // value là int
value = "Năm";     // LỖI: value đã là int!

So sánh: kiểu tường minh và var

Kịch bản Kiểu tường minh var
Kiểu là hiển nhiên
int age = 42;
var age = 42;
Phương thức trả về kiểu phức tạp
HashMap<Integer, String> dict = SomeFunc();
var dict = SomeFunc();
Mảng
String[] names = ...
var names = ...
Mẹo
Trong đa số trường hợp ở các dự án hiện đại, var được dùng cho biến cục bộ. Với tham số, trường và hằng — hãy dùng kiểu tường minh.

2. Từ khóa final: khai báo hằng

Hằng là biến mà giá trị không thể thay đổi sau khi khởi tạo. Hằng giúp mã nguồn đáng tin cậy, dễ hiểu và tránh được việc thay đổi nhầm các con số và chuỗi quan trọng.

  • Số Pi (PI = 3.14159…)
  • Số lượng người dùng tối đa (MAX_USERS = 1000)
  • Tên công ty (COMPANY_NAME = "CodeGym")

Trong Java, để khai báo hằng, dùng bộ sửa đổi final. Nó nói với trình biên dịch: “sau lần gán đầu tiên — không được thay đổi nữa!”


final Tip IMYA_KONSTANTY = znachenie;
Cú pháp khai báo hằng trong Java

Cú pháp

final int DAYS_IN_WEEK = 7;
final double PI = 3.1415926535;
final String GREETING = "Xin chào, Java!";

Điểm quan trọng:

  • Biến với final phải được khởi tạo (ngay tại chỗ hoặc trong constructor — nếu là trường của lớp).
  • Thử thay đổi giá trị sẽ dẫn tới lỗi biên dịch.

Ví dụ: không thể thay đổi biến final

final int MAX_USERS = 100;
MAX_USERS = 200; // Lỗi: không thể gán giá trị mới cho biến final

Chú thích: nếu bỏ comment dòng gán — dự án sẽ không build được.

3. static final: hằng ở cấp lớp

Trong Java, ta thường cần các hằng không phụ thuộc đối tượng cụ thể — “dùng chung” cho toàn bộ lớp. Khi đó ta dùng cặp static + final.

Tại sao static final?

  • static — biến thuộc về lớp (một biến dùng chung).
  • final — giá trị không thể thay đổi.

Cú pháp

public static final double PI = 3.1415926535;
public static final int MAX_USERS = 1000;
public static final String COMPANY_NAME = "CodeGym";

Khai báo ở đâu? Thông thường — ở đầu lớp (trước các phương thức).

Ví dụ sử dụng trong lớp

public class MathUtils 
{
    public static final double PI = 3.1415926535;

    public static double circleLength(double radius) 
    {
        return 2 * PI * radius;
    }
}

Gọi:

double len = MathUtils.circleLength(5);
System.out.println(len); // 31.4159...

Lưu ý: truy cập hằng thông qua tên lớp: MathUtils.PI.

4. Khác biệt giữa chỉ finalstatic final

final — giá trị của trường không thể thay đổi sau khi khởi tạo, nhưng mỗi đối tượng có giá trị riêng.

static final — một hằng dùng chung cho toàn lớp, không phụ thuộc vào đối tượng.

Ví dụ: sự khác biệt trong thực tế

public class User 
{
    public final String name;                      // Mỗi User có tên riêng (final)
    public static final String COMPANY = "CodeGym"; // Một công ty chung cho tất cả (static final)

    public User(String name) 
    {
        this.name = name;
    }
}
User u1 = new User("Vasya");
User u2 = new User("Petya");

System.out.println(u1.name);      // Vasya
System.out.println(u2.name);      // Petya
System.out.println(User.COMPANY); // CodeGym

Kết luận: name — trường bất biến mang tính cá thể, COMPANY — hằng dùng chung.

Quy ước đặt tên hằng

Thông lệ đặt tên hằng dùng CHỮ_IN_HOA_CÓ_DẤU_GẠCH_DƯỚI.

public static final int MAX_USERS = 1000;
public static final double GRAVITY = 9.81;
public static final String DEFAULT_GREETING = "Hello, world!";

Mẹo: nếu thấy kiểu tên như vậy — đừng cố thay đổi giá trị trong mã: trình biên dịch sẽ không cho phép.

5. Thực hành: khai báo và sử dụng hằng

Ví dụ: lớp với các hằng

public class CircleCalculator 
{
    public static final double PI = 3.1415926535;

    public static double getLength(double radius) 
    {
        return 2 * PI * radius;
    }

    public static double getArea(double radius) 
    {
        return PI * radius * radius;
    }
}

Sử dụng:

public class Main 
{
    public static void main(String[] args) 
    {
        double r = 5.0;
        System.out.println("Chu vi đường tròn: " + CircleCalculator.getLength(r));
        System.out.println("Diện tích hình tròn: " + CircleCalculator.getArea(r));
    }
}

Kết quả:

Chu vi đường tròn: 31.415926535
Diện tích hình tròn: 78.5398163375

Cố gắng thay đổi hằng

CircleCalculator.PI = 3.14; // Lỗi biên dịch: cannot assign a value to final variable PI

6. Đặc điểm và lưu ý

Hằng cho đối tượng

Có thể khai báo final cho tham chiếu tới đối tượng, nhưng điều đó không làm đối tượng trở nên bất biến! Nó chỉ cấm gán tham chiếu khác cho biến.

final StringBuilder sb = new StringBuilder("Hello");
sb = new StringBuilder("World"); // Lỗi: không thể gán đối tượng mới
sb.append(", Java!");            // Được phép — chỉ thay đổi trạng thái đối tượng
System.out.println(sb);          // Hello, Java!

Kết luận: final bảo vệ tham chiếu, không phải đối tượng. Để có tính bất biến thực sự, hãy dùng các lớp bất biến (ví dụ, String, List.of(), v.v.).

Dùng hằng thay cho “con số ma thuật”

Phong cách tệ:

double area = 3.1415 * r * r; // 3.1415 là gì? Tại sao lại là số này?

Phong cách tốt:

double area = PI * r * r; // Hiểu ngay là đang dùng số Pi

7. Các lỗi thường gặp khi làm việc với hằng và var

Lỗi №1: cố thay đổi giá trị của biến final. Nếu biến được khai báo với final, gán lại sẽ dẫn tới lỗi biên dịch.

Lỗi №2: cố khai báo hằng thông qua var. Với hằng, luôn dùng kiểu tường minh cùng với final hoặc static final. var — chỉ cho biến cục bộ.

Lỗi №3: đặt tên hằng không đúng. Hằng phải dùng CHỮ_IN_HOA_CÓ_DẤU_GẠCH_DƯỚI. Cách viết như final int maxUsers = 100; làm giảm tính dễ đọc.

Lỗi №4: quên phạm vi hiệu lực. Hằng khai báo bên trong phương thức chỉ thấy trong phương thức đó. Để dùng trong toàn lớp, hãy khai báo ở cấp lớp dưới dạng static final.

Lỗi №5: cho rằng final làm đối tượng bất biến. final cố định tham chiếu, không phải trạng thái đối tượng — đó là hai điều khác nhau.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION