← Về trang Blog
Automation Test

String là gì?

admin· Đăng ngày 30 tháng 6, 2025
String là gì?

Một dòng if (status == "ACTIVE") tưởng vô hại đã khiến cả nghiệp vụ kiểm thử "trượt" qua hàng loạt tài khoản: điều kiện luôn trả về false, dù dữ liệu trên màn hình rõ ràng là "ACTIVE". Bug không nằm ở logic — nó nằm ở chỗ lập trình viên đã so sánh hai String bằng == thay vì .equals(). Với một tester, hiểu đúng String không phải chuyện "kiến thức cơ bản cho có" — đó là ranh giới giữa một test case đáng tin và một test case âm thầm cho kết quả sai.

String xuất hiện ở gần như mọi nơi trong công việc kiểm thử: từ dữ liệu nhập liệu, response của API, đến từng dòng log bạn so khớp. Thế nhưng đây cũng là kiểu dữ liệu dễ gây hiểu lầm nhất: nó immutable (không thể thay đổi), so sánh sai cách thì cho kết quả sai một cách thầm lặng, và xử lý ẩu thì ngốn bộ nhớ mà không ai để ý. Nắm chắc String giúp bạn viết được những kịch bản kiểm thử chính xác và không bị đánh lừa bởi những lỗi "trông thì đúng".

Trong bài viết này, bạn sẽ nắm được:

  • String trong Java thực chất là gì và vì sao nó immutable.
  • Khác biệt cốt lõi giữa ==.equals() — cái bẫy kinh điển khiến test sai.
  • Bộ phương thức xử lý chuỗi thiết yếu, kèm ví dụ dùng được ngay.
  • Khi nào nên dùng StringBuilder thay cho phép nối chuỗi thông thường.

String là gì?

String là kiểu dữ liệu dùng để biểu diễn chuỗi ký tự — hiểu đơn giản là những đoạn văn bản, câu chữ từ vài ký tự đến nguyên cả cuốn tiểu thuyết. Ngay khi bạn viết "Hello, World!" trong chương trình đầu tiên của mình, bạn đã dùng String rồi.

Tạo một String đơn giản như sau:

String greeting = "Hello, Java!";

Vì sao String là "immutable"?

Trong Java, Stringimmutable — tức là không thể thay đổi sau khi đã tạo. Điều này có nghĩa là mỗi lần bạn "chỉnh sửa" một chuỗi, Java âm thầm tạo ra một chuỗi mới và để lại chuỗi cũ trong bộ nhớ. Vậy nên nếu bạn cần thao tác nhiều với chuỗi (ví dụ nối chuỗi trong vòng lặp), hãy cẩn thận để bộ nhớ không biến thành… bãi chiến trường.

Kinh nghiệm thực chiến. Tính immutable chính là lý do bạn không bao giờ được so sánh nội dung hai chuỗi bằng ==. Toán tử == so sánh tham chiếu (hai biến có cùng trỏ về một đối tượng trong bộ nhớ không), chứ không so sánh nội dung ký tự. Đây là cái bẫy khiến vô số bug "lọt lưới" qua các bài kiểm thử.

So sánh chuỗi: ==.equals()

Đây là kiến thức bắt buộc phải nắm trước khi viết bất kỳ điều kiện kiểm tra nào liên quan đến chuỗi. equals kiểm tra chính xác từng ký tự của nội dung, còn equalsIgnoreCase thì thoải mái hơn — không phân biệt chữ hoa, chữ thường.

String name1 = "Alice";
String name2 = "alice";
boolean isEqual = name1.equals(name2);             // Kết quả: false
boolean isEqualIgnoreCase = name1.equalsIgnoreCase(name2); // Kết quả: true
Tiêu chí==.equals()
So sánh điều gìTham chiếu (cùng một đối tượng trong bộ nhớ?)Nội dung (từng ký tự có giống nhau?)
Dùng đểKiểm tra hai biến có trỏ về cùng một objectKiểm tra hai chuỗi có cùng nội dung
Khi so sánh nội dung chuỗiKhông đáng tin — dễ trả về saiCách đúng cần dùng

Quy tắc ghi nhớ: so sánh nội dung chuỗi thì luôn dùng .equals() (hoặc equalsIgnoreCase() nếu không quan tâm hoa/thường), tuyệt đối không dùng ==.

Các phương thức cơ bản làm việc với String

Dưới đây là bộ phương thức cực kỳ hữu ích khi bạn cần "biến hóa" với String trong Java. Mỗi phương thức kèm một ví dụ dùng được ngay.

length() — đếm độ dài chuỗi

Giống như đếm số ký tự trong câu, length() cho bạn biết độ dài của chuỗi.

String message = "Hello, Java!";
int length = message.length(); // Kết quả: 11

"Hello, Java!" có 11 ký tự — đếm cả dấu cách và dấu chấm than.

charAt(int index) — lấy ký tự tại một vị trí

Hàm charAt giúp bạn lấy ra từng ký tự trong chuỗi. Cần ký tự ở vị trí nào, cứ gọi charAt(index).

String name = "Alice";
char firstChar = name.charAt(0); // Kết quả: 'A'

Lưu ý quan trọng. Vị trí trong chuỗi bắt đầu từ 0, không phải từ 1. Vì vậy ký tự "A" của "Alice" nằm ở charAt(0). Đây là nguồn gốc của rất nhiều lỗi lệch một (off-by-one) — đáng nhắc lại nhiều lần.

substring(int beginIndex, int endIndex) — cắt một đoạn chuỗi

Muốn cắt một đoạn từ chuỗi? substring lấy phần từ beginIndex đến endIndexnhưng không tính ký tự ở endIndex. Vị trí vẫn bắt đầu từ 0.

String text = "Hello, world!";
String sub = text.substring(0, 5); // Kết quả: "Hello"

contains(CharSequence s) — kiểm tra có chứa chuỗi con

Muốn biết chuỗi có "chứa" đoạn nào không? contains kiểm tra xem chuỗi con bạn cần tìm có xuất hiện hay không.

String text = "Hello, world!";
boolean hasWorld = text.contains("world"); // Kết quả: true

toLowerCase()toUpperCase() — đổi hoa/thường

Biến chuỗi thành chữ thường hoặc chữ hoa — dùng khi bạn muốn đồng nhất cách viết trước khi so sánh.

String name = "Alice";
String lowerName = name.toLowerCase(); // Kết quả: "alice"
String upperName = name.toUpperCase(); // Kết quả: "ALICE"

trim() — dọn khoảng trắng thừa

Chuỗi của bạn có bị "dính bụi" với những dấu cách thừa ở đầu/đuôi không? trim sẽ dọn dẹp sạch sẽ.

String messyText = "   Hello   ";
String cleanText = messyText.trim(); // Kết quả: "Hello"

replace(CharSequence target, CharSequence replacement) — thay thế chuỗi con

Khi bạn muốn thay một đoạn nào đó trong chuỗi bằng đoạn khác, replace giúp bạn đổi nhanh gọn.

String text = "Hello, world!";
String newText = text.replace("world", "Java"); // Kết quả: "Hello, Java!"

indexOf(String str) — tìm vị trí xuất hiện

Tìm xem chuỗi con xuất hiện lần đầu ở đâu trong chuỗi chính. Nếu không tìm thấy, hàm trả về -1.

String text = "Hello, world!";
int index = text.indexOf("world"); // Kết quả: 7

"world" bắt đầu từ vị trí số 7.

isEmpty() — kiểm tra chuỗi rỗng

Muốn kiểm tra xem chuỗi có rỗng không (không chứa ký tự nào), dùng isEmpty.

String emptyText = "";
boolean isEmpty = emptyText.isEmpty(); // Kết quả: true

Khi nào nên dùng StringBuilder?

String là immutable, mỗi phép nối chuỗi đều sinh ra một đối tượng String mới. Nối vài lần thì không sao, nhưng nối hàng nghìn lần trong vòng lặp — chẳng hạn khi bạn dựng một payload lớn hay ghép một báo cáo kiểm thử — sẽ tạo ra hàng nghìn đối tượng rác và làm chậm chương trình. Khi đó, hãy dùng StringBuilder, một đối tượng có thể thay đổi (mutable) được thiết kế riêng cho việc này.

Tiêu chíStringStringBuilder
Khả năng thay đổiImmutable — mỗi sửa đổi tạo object mớiMutable — sửa trực tiếp trên cùng object
Hiệu năng khi nối nhiều lầnChậm, tốn bộ nhớ (sinh nhiều rác)Nhanh, tiết kiệm bộ nhớ
Phù hợp khiChuỗi cố định, nối ít lầnNối/sửa chuỗi nhiều lần, trong vòng lặp

Kết luận

Với String, hãy ghi nhớ ba điều cốt lõi: nó immutable, so sánh nội dung phải dùng .equals() chứ không phải ==, và khi nối chuỗi nhiều lần thì nên chuyển sang StringBuilder. Nắm chắc bộ phương thức cơ bản ở trên, bạn đã có đủ "vũ khí" để xử lý chuỗi một cách chính xác — nền tảng vững chắc cho cả lập trình lẫn viết kịch bản kiểm thử tự động.

Bạn đã từng "dính" bug nào vì so sánh chuỗi sai cách chưa? Hãy chia sẻ trải nghiệm của bạn để cộng đồng cùng học hỏi và tránh lặp lại những cái bẫy kinh điển này.