1. So sánh
Các lập trình viên luôn cần so sánh các biến khác nhau với nhau. Nhưng, như bạn đã thấy, mọi thứ không đơn giản như vậy.
Các số nguyên rất dễ so sánh — bạn chỉ cần sử dụng ==là xong. Để so sánh các số thực , bạn phải so sánh hiệu của chúng (hay đúng hơn là giá trị tuyệt đối của hiệu) với một số rất nhỏ.
So sánh các chuỗi thậm chí còn khó hơn. Trên hết, điều này là do chuỗi là đối tượng. Hơn nữa, các lập trình viên thường muốn so sánh chuỗi khác đi một chút tùy thuộc vào tình huống.
2. Cách sắp xếp bộ nhớ chuỗi
Như bạn đã thấy, chuỗi được lưu trữ trong bộ nhớ khác với số nguyên và số thực:

Hai khối bộ nhớ được sử dụng để lưu trữ các chuỗi: một khối lưu trữ chính văn bản (kích thước của nó phụ thuộc vào kích thước của văn bản) trong khi khối thứ hai (4 byte) lưu trữ địa chỉ của khối đầu tiên.
Mặc dù một lập trình viên có kinh nghiệm sẽ nói điều gì đó như " String strbiến lưu trữ một tham chiếu đến một Stringđối tượng.
3. Gán tham chiếu cho một chuỗi
Lợi ích của phương pháp này trở nên rõ ràng khi bạn cần gán một biến chuỗi cho một biến chuỗi khác. Ví dụ:
String text = "This is a very important message";
String message = text;
Và đây là kết quả bộ nhớ sẽ chứa:
Sau loại thao tác gán này, Stringđối tượng vẫn giữ nguyên vị trí của nó và chỉ địa chỉ của nó (tham chiếu đến đối tượng) được sao chép vào biến message.
4. Làm việc với tham chiếu và đối tượng
Nhưng nếu bạn quyết định chuyển đổi một chuỗi thành chữ hoa (chữ in hoa), máy Java sẽ làm đúng mọi thứ: bạn sẽ có hai Stringđối tượng và các biến textvà messagesẽ lưu trữ các tham chiếu, mỗi tham chiếu đến đối tượng riêng của nó.
Ví dụ:
String text = "This is a very important message";
String message = text.toUpperCase();
Và đây là kết quả bộ nhớ sẽ chứa:

Xin lưu ý rằng toUpperCase()phương thức này không thay đổi chuỗi mà nó được gọi. Thay vào đó, nó tạo ra một chuỗi mới (đối tượng mới) và trả về một tham chiếu đến nó.
Làm thế nào về một ví dụ thậm chí thú vị hơn. Giả sử bạn quyết định chuyển một chuỗi tới một Scannerđối tượng (để nó đọc các giá trị từ chuỗi).
Ví dụ:
String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();
Bạn có thể tìm hiểu thêm về cách Scannerhoạt động của lớp tại đây .
Đây là cách tất cả sẽ được lưu trữ trong bộ nhớ:

Trong trường hợp này, một Stringđối tượng duy nhất vẫn còn trong bộ nhớ như cũ — chỉ các tham chiếu đến đối tượng đó mới được truyền xung quanh và lưu trữ trong các biến.
5. So sánh các tham chiếu đến Stringcác đối tượng
Và cuối cùng, chúng ta đã đến phần thú vị: so sánh chuỗi.
Có hai toán tử bạn có thể sử dụng để so sánh các biến chuỗi: ==(bằng) và !=(không bằng). Bạn không thể sử dụng các toán tử "lớn hơn", "nhỏ hơn" hoặc "lớn hơn hoặc bằng" — trình biên dịch sẽ không cho phép điều đó.
Nhưng có một sắc thái thú vị ở đây: cái gì thực sự được lưu trữ trong các biến chuỗi? Đúng vậy: địa chỉ (tham chiếu) đến các đối tượng. Và chính những địa chỉ này sẽ được so sánh:
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
Đây là những gì sẽ có trong bộ nhớ:

Các biến messagevà texttham chiếu đến (lưu trữ địa chỉ của) cùng một đối tượng. Nhưng các biến s1và s2lưu trữ các tham chiếu đến các đối tượng rất giống nhau nhưng khác biệt.
Và nếu so sánh 4 biến này trong code thì bạn sẽ được kết quả như sau:
| Mã số | Đầu ra bảng điều khiển |
|---|---|
|
|
GO TO FULL VERSION