Thứ Tư, 5 tháng 6, 2013

So sánh 2 chuỗi String trong java

Thảo luận: String trong Java
- Chúng ta đã biết kiểu String (chuỗi) trong java.
- Và trong lúc học thì các thầy cô luôn dặn rằng : muốn so sánh 2 chuỗi thì nên dùng phương thức equals, không nên dùng toán tử ==. Vậy thì tại sao???

- Chúng ta cùng xem qua ví dụ này:

Mã:

String s1 = "Hello World!";
String s2 = "Hello World!";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));



- Điều hiển nhiên là chương trình sẽ in ra 2 giá trị true, tức qua 2 cách so sánh 2 chuỗi đều bằng nhau.
- Tuy nhiên hãy xét tiếp ví dụ thứ 2
Mã:

String s1 = "Hello World!";
String s2 = new String("Hello World!");

System.out.println(s1 == s2);
System.out.println(s1.equals(s2));

- Chỉ có 1 kết quả true khi dùng equals, vậy tại sao s1 == s2 lại cho kết quả false trong khi s1,s2 chẳng khác nhau gì cả. Có người bảo tại cách định nghĩa 2 chuỗi không giống nhau, vậy xem tiếp ví dụ 3
Mã:

String s1 = new String("Hello World!");
String s2 = new String("Hello World!");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));


- Kết quả vẫn y như ví dụ 2. Vậy thì câu trả lời trên là sai.

- String trong java cũng được coi như 1 đối tượng, khi bạn khai báo String s1 = "Hello World!"; là đã định nghĩa ra 1 đối tượng String lưu giá trị "Hello World!" và s1 sẽ tham chiếu đến đối tượng này.

- Khi bạn khai báo tiếp String s2 = "Hello World!"; ở đây sẽ ko tạo ra thêm đối tượng mới, mà s2 sẽ tham chiếu đến đối tượng đã được tạo ra khi khai báo s1. Tại sao kì vậy?.

- Vì trong quá trình thực thi, JVM luôn sắp xếp các đối tượng chuỗi bằng nhau để có thể chia sẻ cho nhau, giảm bớt việc tạo đối tượng mới. Cần chú ý, chỉ những chuỗi nào được coi là "string contants" mới có thể chia sẽ, tức là những giá trị chuỗi ko phải tạo ra bằng toán tử như toán tử + hay như phương thức subtring, etc.

- Vì vậy, Khi dùng == để so sánh 2 chuỗi, chỉ khi nào 2 biến cùng tham chiếu đến cùng 1 đối tượng String thì mới trả về giá trị true.

- Đến đây chắc sẽ có nhiều người thắc mắc, vì s1, s2 cùng tham chiếu đến 1 đối tượng String nên khi thay đổi chuỗi (+,subtring) ở s1 thì liệu s2 có thay đổi theo ko. Câu trả lời sẽ là không.

+ Đầu tiên hãy chú ý phát biểu sau: String trong java là kiểu giá trị không thể thay đổi được (immutable). Xem ví dụ thứ 4:
Mã:

String s1 = "Hello";
s1 += " World!";
System.out.println(s1); //kết quả in ra sẽ là Hello World!


++ Sau khi xem ví dụ này, nhiều người sẽ cho rằng phát biểu trên là sai, vì rõ ràng trong ví dụ 4, biến s1 có thể thay đổi giá trị từ "Hello" cộng thêm " World!" thành "Hello World!"

++ Tuy nhiên suy nghĩ đó là sai, khi s1 += " World!", nó không thay đổi giá trị "Hello" ở đối tượng String cũ (vì nó ko thể thay đổi) mà là tạo ra 1 đối tượng String mới có giá trị = giá trị đối tượng String cũ + " World!", khi đó s1 sẽ chuyển tham chiếu từ đối tượng String cũ sang đối tượng String mới. Và đối tượng String cũ nếu ko được chia sẽ cho biến nào nữa sẽ được GC (Garbage Collection) dọn dẹp.

++ Bây giờ đã rõ ràng: String trong java là kiểu giá trị không thể thay đổi được, nếu ta thấy thay đổi thì đó chỉ là sự thay đổi tham chiếu từ đối tượng cũ sang mới.

- Quay lại ví dụ 2
Mã:

String s1 = "Hello World!";
String s2 = new String("Hello World!");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));


+ hàng thứ nhất sẽ tạo ra 1 đối tượng String có giá trị "Hello World!" và s1 tham chiếu đến nó;
+ Tuy nhiên cách khai báo ở hàng thứ hai, như ta thấy có từ khóa new, thì tất nhiên nó sẽ tạo 1 đối tương String thứ 2 (mới) và s2 sẽ tham chiếu đến nó.
+ Chính vì vậy khi ta dùng == để so sánh sẽ cho ra kết quả false vì s1, s2 không cùng tham chiếu đến 1 đối tượng String.

- Cuối cùng ta rút ra các điều cần ghi nhớ sau:

1. Khi dùng == để so sánh 2 chuỗi, chỉ khi nào 2 biến cùng tham chiếu đến cùng 1 đối tượng String thì mới trả về giá trị true.

2. Để tránh các sai sót trong chương trình ta luôn phải dùng equals khi so sánh giá trị 2 chuỗi.

3. Trong quá trình thực thi, JVM luôn sắp xếp các đối tượng chuỗi bằng nhau để có thể chia sẻ cho nhau, giảm bớt việc tạo đối tượng mới. Cần chú ý, chỉ những chuỗi nào được coi là string contants mới có thể chia sẽ, tức là những giá trị chuỗi ko phải tạo ra bằng toán tử như toán tử + hay như phương thức subtring.

4. String trong java là kiểu giá trị không thể thay đổi được (immutable), nếu ta thấy sự thay đổi thì đó chỉ là sự chuyển tham chiếu từ đối tượng cũ sang mới.

 

0 nhận xét:

Đăng nhận xét