Trong ví dụ đã cung cấp, chỉ có một đối tượng được tạo ra. Ban đầu, JVM sẽ không tìm thấy bất kỳ đối tượng chuỗi nào có giá trị "Welcome" trong chuỗi hằng số, vì vậy nó sẽ tạo ra một đối tượng mới. Sau đó, nó sẽ tìm thấy chuỗi có giá trị "Welcome" trong pool, nó sẽ không tạo ra một đối tượng mới mà sẽ trả về tham chiếu đến cùng một phiên bản. Trong bài viết này, chúng ta sẽ tìm hiểu về các chuỗi trong Java.
Chuỗi là gì trong Java?
Chuỗi là loại đối tượng có thể lưu trữ các ký tự giá trị và trong Java, mỗi ký tự được lưu trữ trong 16 bit, sử dụng mã hóa UTF 16-bit. Một chuỗi hoạt động giống như một mảng các ký tự trong Java.
Ví dụ:
String name = "Geeks";
Dưới đây là một ví dụ về một chuỗi trong Java:
Cách tạo chuỗi
Có hai cách để tạo ra một chuỗi trong Java:
- Chuỗi chữ
- Sử dụng từ khóa "new"
Cú pháp:
= "";
1. Chuỗi chữ
Để làm cho Java hiệu quả hơn về bộ nhớ (vì không tạo ra đối tượng mới nếu nó đã tồn tại trong chuỗi hằng số), chúng ta có thể sử dụng chuỗi chữ.
Ví dụ:
String demoString = "GeeksforGeeks";
2. Sử dụng từ khóa "new"
- String s = new String("Welcome");
- Trong trường hợp này, JVM sẽ tạo một đối tượng chuỗi mới trong bộ nhớ heap thông thường và chuỗi "Welcome" sẽ được đặt trong pool chuỗi hằng số. Biến s sẽ tham chiếu đến đối tượng trong heap (không phải pool).
Ví dụ:
String demoString = new String ("GeeksforGeeks");
Giao diện và Lớp trong Chuỗi trong Java
-
CharBuffer: Lớp này triển khai giao diện CharSequence. Lớp này được sử dụng để cho phép buffer ký tự được sử dụng thay vì CharSequence. Một ví dụ về cách sử dụng là gói biểu thức chính quy java.util.regex.
-
String: Đây là một chuỗi các ký tự. Trong Java, các đối tượng chuỗi là không thay đổi, điều này có nghĩa là hằng số và không thể thay đổi sau khi được tạo.
Giao diện CharSequence
Giao diện CharSequence được sử dụng để biểu diễn chuỗi các ký tự trong Java. Các lớp được triển khai bằng giao diện CharSequence được liệt kê dưới đây và cung cấp nhiều chức năng như substring, lastoccurence, first occurence, concatenate, toupper, tolower, v.v.
- String
- StringBuffer
- StringBuilder
1. String
String là một lớp không thay đổi, điều này có nghĩa là không thể thay đổi sau khi được tạo và nếu muốn thay đổi, chúng ta cần tạo một đối tượng mới và thậm chí chức năng nó cung cấp như toupper, tolower, v.v. tất cả đều trả về một đối tượng mới, không sửa đổi đối tượng ban đầu. Nó tự động an toàn luồng.
Cú pháp
String str = "geeks";
hoặc
String str = new String("geeks");
2. StringBuffer
StringBuffer là một lớp đồng loạt với String, nó có thể thay đổi và là một lớp an toàn luồng, chúng ta có thể sử dụng nó khi có môi trường đa luồng và đối tượng được chia sẻ của bộ đệm chuỗi, được sử dụng bởi nhiều luồng. Vì nó an toàn luồng nên có thêm chi phí, vì vậy nó chủ yếu được sử dụng cho chương trình đa luồng.
Cú pháp:
StringBuffer demoString = new StringBuffer("GeeksforGeeks");
3. StringBuilder
StringBuilder trong Java đại diện cho một phiên bản thay thế String và StringBuffer, vì nó tạo ra một chuỗi có thể thay đổi của các ký tự và nó không an toàn luồng. Nó chỉ được sử dụng trong chính 1 luồng, vì vậy không có chi phí phụ, nên nó chủ yếu được sử dụng cho chương trình đơn luồng.
Cú pháp:
StringBuilder demoString = new StringBuilder(); demoString.append("GFG");
StringTokenizer
Lớp StringTokenizer trong Java được sử dụng để tách một chuỗi thành các token.
Ví dụ:
Một đối tượng StringTokenizer bảo quản một vị trí hiện tại trong chuỗi để tách thành các token. Một số hoạt động tiến vị trí hiện tại này vượt qua các ký tự được xử lý. Một token được trả về bằng cách lấy một chuỗi con của chuỗi được sử dụng để tạo đối tượng StringTokenizer.
StringJoiner
StringJoiner là một lớp trong gói java.util được sử dụng để xây dựng một chuỗi các ký tự được phân tách bằng một phân cách và tùy chọn bắt đầu bằng một tiền tố được cung cấp và kết thúc bằng một hậu tố được cung cấp. Mặc dù bạn cũng có thể làm điều này bằng cách sử dụng lớp StringBuilder để nối một phân tách sau mỗi chuỗi, StringJoiner cung cấp một cách dễ dàng để làm điều đó mà không cần viết mã phức tạp.
Cú pháp:
public StringJoiner(CharSequence delimiter)
Dưới đây là một ví dụ về cách khai báo một chuỗi:
String demoString = "Welcome";
Ở đây, JVM kiểm tra Pool chuỗi. Nếu chuỗi không tồn tại, thì một phiên bản chuỗi mới được tạo ra và đặt trong pool. Nếu chuỗi tồn tại, thì nó sẽ không tạo ra đối tượng mới. Thay vào đó, nó sẽ trả về tham chiếu đến cùng một phiên bản. Bộ nhớ cache chứa các phiên bản chuỗi này được gọi là Pool chuỗi hoặc String Pool. Trong các phiên bản trước của Java lên đến JDK 6, pool chuỗi nằm trong không gian PermGen (Generation Vĩnh viễn). Nhưng trong JDK 7, nó di chuyển vào khu vực heap chính.
Chuỗi bất biến trong Java
Trong Java, các đối tượng chuỗi là không thay đổi. Bất biến đơn giản là không thể sửa đổi hoặc thay đổi. Sau khi một đối tượng chuỗi được tạo, dữ liệu hoặc trạng thái của nó không thể thay đổi, nhưng một đối tượng chuỗi mới sẽ được tạo ra.
Dưới đây là cài đặt của chủ đề:
Ở đây, "Sachin" không được thay đổi nhưng một đối tượng mới được tạo ra với chuỗi "Sachin Tendulkar". Đó là lý do vì sao một chuỗi được biết đến là bất biến.
Như bạn có thể thấy trong hình dưới đây, có hai đối tượng được tạo ra nhưng biến s vẫn trỏ vào "Sachin" và không phải "Sachin Tendulkar". Nhưng nếu chúng ta gán nó một cách rõ ràng cho biến tham chiếu, nó sẽ trỏ vào đối tượng "Sachin Tendulkar".
Ví dụ:
Phân bổ bộ nhớ của chuỗi
Khi một đối tượng Chuỗi được tạo dưới dạng chữ, đối tượng sẽ được tạo trong pool chuỗi. Điều này cho phép JVM tối ưu hóa việc khởi tạo chữ ký chuỗi.
Ví dụ:
String demoString = "Geeks";
Chuỗi cũng có thể được khai báo bằng toán tử new, tức là được cấp phát động. Trong trường hợp chuỗi được cấp phát động, chúng sẽ được gán một vị trí bộ nhớ mới trong heap, chuỗi này sẽ không được thêm vào pool chuỗi.
Ví dụ:
String demoString = new String("Geeks");
Nếu bạn muốn lưu trữ chuỗi này trong pool chuỗi, bạn cần phải "intern" nó.
Ví dụ:
String internedString = demoString.intern(); // điều này sẽ thêm chuỗi vào pool chuỗi.
Rất ưu tiên sử dụng chuỗi chữ vì nó cho phép JVM tối ưu hóa việc phân bổ bộ nhớ.
Dưới đây là một ví dụ về cách khai báo một chuỗi:
Lưu ý: Đối tượng chuỗi được lưu trữ trong một vùng nhớ đặc biệt được gọi là pool chuỗi.
Tại sao pool chuỗi di chuyển từ PermGen vào khu vực heap thông thường?
Không gian PermGen bị giới hạn, kích thước mặc định chỉ là 64 MB. Điều này là một vấn đề khi tạo và lưu trữ quá nhiều đối tượng chuỗi trong không gian PermGen. Đó là lý do tại sao pool chuỗi đã được di chuyển vào một khu vực heap lớn hơn. Để làm cho Java hiệu quả hơn về bộ nhớ, khái niệm chữ chung được sử dụng. Bằng cách sử dụng từ khóa 'new', JVM sẽ tạo một đối tượng chuỗi mới trong khu vực heap thông thường ngay cả khi cùng một đối tượng chuỗi đã có trong pool chuỗi.
Ví dụ:
String demoString = new String("Bhubaneswar");
Hãy xem khái niệm này với một chương trình Java và hình dung cấu trúc bộ nhớ JVM thực tế:
Dưới đây là cài đặt của phương pháp trên:
Lưu ý: Tất cả các đối tượng trong Java được lưu trong heap. Biến tham chiếu đến đối tượng được lưu trữ trong các vùng ngăn xếp hoặc chúng có thể được chứa trong các đối tượng khác, đặt chúng trong vùng heap.