Cùng tìm hiểu String trong Java nào


Cùng tìm hiểu String trong Java nào
Trong lập trình nói chung, String là một mảng gồm các kí tự. Khái niệm có vẻ đơn giản, nhưng trong Java, người ta không chỉ dừng lại ở mức đơn giản như thế. Hôm nay mình sẽ tập trung vào 2 mục tiêu:
1.  Các thành phần của String
2.  Tổ chức lưu trữ trong String
Phần 1: Các thành phần của String
String bản chất là một đối tượng được tạo thông qua lớp String. Vì Java có cung cấp mã nguồn của các lớp nên chúng ta cùng nhau khai thác nó để hiểu rõ hơn nhé.
Vì là đối tượng nên chúng ta sẽ xem thuộc tính của nó trước:

Như chúng ta thấy, lớp String có 2 thuộc tính: value[] và hash (ở phiên bản cũ thì có 4 thuộc tính: value[], offset, count và hash (xem chi tiết tại: http://www.docjar.com/html/api/java/lang/String.java.html) ).
Đầu tiên ta thấy rõ value[] là một mảng gồm các char, vậy tức là String trong Java được biểu diễn dưới hình thức của char array. Để đảm bảo hơn, ta thử soi hàm length() của class String thực hiện thế nào: 

Thế thì chuẩn luôn rồi, phương thức length() sử dụng phương thức tính chiều dài của mảng áp dụng trên value, tức mảng value chính là đại diện của String.
Cái thứ 2 ít quan tâm hơn là hash. Thuộc tính hash lưu trữ dạng mã hóa của chuỗi, mặc định của nó là 0, khi sử dụng hàm hashCode(), nó sẽ hash chuỗi và trả về như sau

Thuộc tính này chỉ thay đổi giá trị khi hashCode() thực thi. Mà phần này chúng ta chỉ hiểu thôi, đừng quan tâm quá.
Về offset và count, nó có nghĩa là vị trí đầu tiên và số lượng của String. Phần này đã bị lược đi có lẽ do Java cảm thấy nó thừa. (Bạn nào quan tâm thì hãy so sánh subString() giữa 2 class cũ và mới sẽ thấy sự khác biệt trước và sau khi lược bỏ).
Thôi đi xa quá rồi. Chúng ta cùng tiếp tục giải quyết vấn đề thứ 2:
Phần 2: Tổ chức lưu trữ trong String
Trong Java, khi khởi tạo một đối tượng, giá trị này sẽ lưu vào trong mảng value.


Có 2 cách khởi tạo đối tượng:
Cách 1: Dùng toán tử new ( String s = new String(“Hello World”) )
Cách 2: Sử dụng dấu “=” ( String s = “Hello World” )
Điểm giống nhau là cả 2 đều khởi tạo và lưu giá trị vào trong thuộc tính value. Tất nhiên là sẽ có điểm khác nhau giữa 2 cách này, chúng ta cùng theo dõi tiếp.

Chúng ta cùng làm quen với khái niệm String literal và String pool. Như các bạn đã biết, khi khởi tạo 1 đối tượng bằng từ khóa new, giá trị sẽ được lưu trong bộ nhớ heap. Nhưng đặc biệt, khi khởi tạo bằng “=”, phép khởi tạo này định nghĩa giá trị bên phải dấu bằng là một literal và lưu vào trong một khu vực đặc biệt của heap gọi là String pool. Điểm đặc biệt của nơi này là khi một đối tượng khởi tạo với giá trị là String literal (tức dùng phép “=”), nó sẽ dò trong String pool xem có xâu nào trùng với xâu mình cần dò không. Nếu trùng, đối tượng sẽ trỏ vào vị trí đó. Nếu không, một giá trị mới sẽ lưu vào trong String pool.
Ví dụ trên hình, ta có s1 khởi tạo với từ khóa new, nên sẽ lưu trong heap và bên ngoài String pool. Tiếp đó, s2 khởi tạo bằng “=”, nó sẽ dò và lưu vào trong String pool. Kế nữa, s3 cũng khởi tạo bằng “=”, lúc này s3 dò và tìm ra vị trí chứa “Hi” trong String pool, s3 ngay lập tức trỏ tới vị trí này (tức s2 và s3 cùng trỏ tới 1 nơi chứa giá trị). s4 cũng tương tự như s1.
Giả sử khi ta so sánh s1==s2, s2==s3, s4==s1 (ta hiểu là so địa chỉ mà biến trỏ tới), ta thu được kết quả false, true, false. Nguyên nhân như đã giải thích ở trên.
Còn một đặc điểm trong String gọi là immutable (bất biến). Bất biến ở đây nghĩa là giá trị trong một ô nhớ không bị thay đổi. Giả sử ta có dòng code

Ta có sơ đồ trước và sau khi substring như sau

Khi thực hiện subString và “gán” vào s1 (thực ra là khởi tạo), lúc này s1 sẽ không thay đổi giá trị mà thực hiện trỏ tới ô nhớ mới chứa kí tự đã subString. Ô nhớ chứa “abc” vẫn không hề thay đổi, đó chính là tính bất biến của String.
Việc sử dụng String pool trong Java giúp cho người lập trình tiết kiệm bộ nhớ rất nhiều, chỉ cần trỏ vào cùng 1 vị trí là đã đỡ tốn thêm bộ nhớ để lưu trữ rồi.
Tổng kết lại, ta nhớ các ý sau đây:
·    String là đối tượng
·    String được biểu diễn dưới dạng tập hợp mảng char
·    String pool và String literal
·    String có tính bất biến
Nội dung bài viết thuộc về Lê Công Diễn.

Người viết: Lê Công Diễn
Mang đi nhớ ghi nguồn


Nhận xét

Bài đăng phổ biến từ blog này

Deploy project Springboot MIỄN PHÍ sử dụng Render

Ứng dụng Mã hóa bất đối xứng (Asymmetric cryptography) vào Chữ ký số (Digital Signature)

API và HTTP - Một số khái niệm cơ bản cần biết về Web (Phần 2)