1. String là gì?
Trong Java, String về cơ bản là một đối tượng biểu diễn chuỗi các giá trị char. Một mảng các ký tự hoạt động giống như Java string
char[] ch = {'T', 'â', 'y', 'J', 'a', 'v', 'a'}; String s = new String(ch);
→
String s = "TâyJava";
Lớp Java String cung cấp nhiều phương thức để thực hiện các để xử lý String như compare()
, concat()
, equals()
, split()
, length()
, replace()
, compareTo()
, intern()
, substring()
, v.v.
Interface CharSequence được sử dụng để biểu diễn chuỗi ký tự. Các lớp String, StringBuffer và StringBuilder đều implements nó. Điều đó có nghĩa là chúng ta có thể tạo một string trong Java bằng cách sử dụng ba lớp này.
Java String là bất biến nghĩa là không thể thay đổi kích thước của nó. Bất cứ khi nào chúng ta thay đổi bất kỳ string nào đó thì một instance mới sẽ được tạo ra. Nếu bạn muốn sử dụng các chuỗi có thể thay đổi thì có thể dùng StringBuffer và StringBuilder.
2. Làm thế nào để khởi tạo một Java String ?
2.1 Sử dụng string literal
String được tạo ra với dấu “”
String s1 = "Welcome to Tay Java";
Mỗi lần bạn tạo ra một String, JVM sẽ kiểm tra “string constant pool” trước. Nếu String đã tồn tại trong pool thì một tham chiếu đến instance đó sẽ được tạo ra. Nếu String đó chưa tồn tại thì JVM sẽ tạo string mới.
String s1 = "Welcome to Tay Java"; String s2 = "Welcome to Tay Java"; // JVM không tạo một string mới
Tại sao Java sử dụng khái niệm String literal?
Để làm cho Java sử dụng bộ nhớ hiệu quả hơn, Bởi vì không có đối tượng mới nào được tạo nếu nó đã tồn tại trong Spring constant pool.
2.2 Sử dụng từ khóa new
String s1 = new String("Welcome to Tây Java");
Trong trường hợp như vậy, JVM sẽ tạo một đối tượng String mới trong bộ nhớ heap bình thường (không phải pool) và giá trị “Welcome to Tây Java” theo nghĩa đen sẽ được đặt trong Spring constant pool. Biến s sẽ tham chiếu đến đối tượng trong heap (không phải pool).
2.3 Các method trong class String
# | Method | Mô tả |
1 | char charAt(int index) | Trả về giá trị char cho index cụ thể |
2 | int length() | Trả về độ dài của string |
3 | static String format(String format, Object… args) | Trả về một String đã được định dạng |
4 | static String format(Locale locale, String format, Object… args) | Trả về một String đã được định dạng theo ngôn ngữ đã cho |
5 | String substring(int beginIndex) | Trả về substring từ vị trí index cho trước |
6 | String substring(int beginIndex, int endIndex) | Trả về substring từ index bắt đầu đến index kết thúc |
7 | boolean contains(CharSequence s) | Nó trả về giá trị đúng hoặc sai sau khi khớp với string giá trị char |
8 | static String join(CharSequence delimiter, CharSequence… elements) | Trả về một string đã nối |
9 | static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) | Trả về một string đã nối |
10 | boolean equals(Object another) | Kiểm tra xem string có giống với đối tượng đã cho hay không |
11 | boolean isEmpty() | Kiểm tra string có bị rỗng không (null hoặc blank) không ? |
12 | String concat(String str) | Nối string đã chỉ định |
13 | String replace(char old, char new) | Thay thế tất cả các lần xuất hiện của giá trị char được chỉ định |
14 | String replace(CharSequence old, CharSequence new) | Thay thế tất cả các lần xuất hiện của CharSequence đã chỉ định |
15 | static String equalsIgnoreCase(String another) | So sánh với một string khác không kiểm tra chữ hoa chữ thường |
16 | String[] split(String regex) | Trả về một string phân tách khớp với regex |
17 | String[] split(String regex, int limit) | Trả về một string phân tách khớp với regex và limit |
18 | String intern() | Trả về một string đã được đồng bộ trong String constant pool |
19 | int indexOf(int ch) | Trả về giá trị char được chỉ định |
20 | int indexOf(int ch, int fromIndex) | Trả về giá trị char được chỉ định bắt đầu theo index đã cho |
21 | int indexOf(String substring) | Trả về chỉ mục string con được chỉ định |
22 | int indexOf(String substring, int fromIndex) | Trả về chỉ mục string con được chỉ định bắt đầu theo index đã cho |
23 | String toLowerCase() | Trả về một string thường |
24 | String toLowerCase(Locale locale) | Trả về một string thường theo ngôn ngữ được chỉ định |
25 | String toUpperCase() | Trả về một STRING IN HOA |
26 | String toUpperCase(Locale locale) | Trả về một STRING IN HOA theo ngôn ngữ được chỉ định |
27 | String trim() | Loại bỏ khoảng trắng ở trước và sau String |
28 | static String valueOf(int value) | Chuyển đổi kiểu từ dữ liệu đã cho thành string. Đây là overloading method |
4. Câu hỏi phỏng vấn Java String
4.1 String trong Java là gì?
String trong Java là một lớp đại diện cho chuỗi ký tự. Chuỗi trong Java là bất biến (immutable), nghĩa là một khi chuỗi đã được tạo, nội dung của nó không thể thay đổi.
4.2 Sự khác biệt giữa String
, StringBuilder
và StringBuffer
là gì?
String
là bất biến (immutable) nghĩa là sau khi tạo, chuỗi không thể thay đổi.StringBuilder
là một lớp có thể thay đổi (mutable) và không đồng bộ (non-synchronized). Nó phù hợp khi cần thực hiện nhiều thao tác trên chuỗi và không cần đảm bảo tính an toàn luồng (thread-safety).StringBuffer
cũng là một lớp có thể thay đổi nhưng được đồng bộ (synchronized), nên nó an toàn cho các chương trình đa luồng (thread-safe). Tuy nhiên, nó chậm hơn so vớiStringBuilder
do có cơ chế đồng bộ hóa.
4.3 String pool là gì?
- String pool (hoặc interned strings) là một khu vực đặc biệt trong bộ nhớ heap của Java, nơi lưu trữ các chuỗi String. Khi bạn tạo một đối tượng
String
bằng cách sử dụng dấu ngoặc kép (" "
), Java sẽ kiểm tra trong String pool xem chuỗi đó đã tồn tại hay chưa. Nếu tồn tại, Java sẽ trả về tham chiếu đến chuỗi đó thay vì tạo một chuỗi mới. Điều này giúp tiết kiệm bộ nhớ.
4.4 Tại sao String là bất biến trong Java?
Có một số lý do tại sao String trong Java là bất biến:
- Bảo mật: Các chuỗi bất biến giúp tránh các lỗ hổng bảo mật tiềm ẩn. Ví dụ, chuỗi mật khẩu được truyền qua nhiều lớp mà không lo bị thay đổi.
- Tính hiệu quả: Bất biến cho phép String pool hoạt động hiệu quả hơn vì các chuỗi không thể bị thay đổi, giúp tiết kiệm bộ nhớ.
- Thread-Safety: Do các chuỗi không thể thay đổi nên chúng an toàn trong môi trường đa luồng (thread-safe).
4.5 Làm thế nào để so sánh hai chuỗi trong Java?
– Sử dụng phương thức equals()
để so sánh giá trị của hai chuỗi:
String str1 = "hello"; String str2 = "hello"; if (str1.equals(str2)) { System.out.println("Hai chuỗi bằng nhau"); }
– Sử dụng toán tử ==
để so sánh tham chiếu (nếu hai chuỗi trỏ đến cùng một đối tượng trong bộ nhớ):
if (str1 == str2) { System.out.println("Hai chuỗi cùng tham chiếu"); }
– Sử dụng phương thức compareTo()
để so sánh từ điển:
int result = str1.compareTo(str2); if (result == 0) { System.out.println("Hai chuỗi bằng nhau"); } else if (result > 0) { System.out.println("Chuỗi 1 lớn hơn chuỗi 2"); } else { System.out.println("Chuỗi 1 nhỏ hơn chuỗi 2"); }
4.6 Sự khác biệt giữa ==
và equals()
khi so sánh chuỗi?
- Toán tử
==
so sánh tham chiếu của hai đối tượng, nghĩa là nó kiểm tra xem hai chuỗi có cùng trỏ đến cùng một vị trí bộ nhớ hay không. - Phương thức
equals()
so sánh nội dung (giá trị) của hai chuỗi.
4.7 Cách tạo chuỗi mới từ một mảng ký tự (char array)?
Bạn có thể tạo một chuỗi từ mảng ký tự bằng cách sử dụng constructor của lớp String
char[] charArray = {'H', 'e', 'l', 'l', 'o'}; String str = new String(charArray);
4.8 Phương thức substring()
trong Java hoạt động như thế nào?
Phương thức substring()
được sử dụng để trích xuất một phần của chuỗi:
String str = "Hello World"; String subStr = str.substring(0, 5); // Kết quả là "Hello"
Lưu ý: substring()
lấy ký tự từ chỉ mục bắt đầu và kết thúc trước chỉ mục kết thúc (exclusive).
4.9 Làm thế nào để chuyển đổi một chuỗi thành mảng ký tự (char array)?
Bạn có thể sử dụng phương thức toCharArray()
để chuyển đổi một chuỗi thành mảng ký tự:
String str = "Hello"; char[] charArray = str.toCharArray();
4.10 Phương thức String.valueOf()
có tác dụng gì?
Phương thức String.valueOf()
chuyển đổi các kiểu dữ liệu khác (như số nguyên, boolean, đối tượng) thành chuỗi:
int number = 10; String str = String.valueOf(number); // Chuyển đổi số nguyên thành chuỗi
4.11 Phương thức trim()
trong String có tác dụng gì?
Phương thức trim()
loại bỏ các ký tự khoảng trắng (space) ở đầu và cuối chuỗi:
String str = " Hello World "; String trimmedStr = str.trim(); // Kết quả là "Hello World"
4.12 Làm thế nào để kiểm tra nếu một chuỗi trống hoặc rỗng?
– Bạn có thể sử dụng phương thức isEmpty()
để kiểm tra xem chuỗi có trống hay không (chuỗi có độ dài bằng 0):
String str = ""; if (str.isEmpty()) { System.out.println("Chuỗi trống"); }
– Để kiểm tra xem chuỗi có rỗng hoặc chứa khoảng trắng, bạn có thể kết hợp trim() và isEmpty():
if (str.trim().isEmpty()) { System.out.println("Chuỗi chỉ chứa khoảng trắng"); }
4.13 Làm thế nào để nối (concatenate) hai chuỗi trong Java?
Bạn có thể sử dụng toán tử +
hoặc phương thức concat()
để nối hai chuỗi:
String str1 = "Hello"; String str2 = "World"; String result = str1 + " " + str2; // Kết quả là "Hello World"
Hoặc:
String result = str1.concat(" ").concat(str2); // Kết quả là "Hello World"
4.14 Làm thế nào để chuyển đổi một chuỗi thành chữ hoa hoặc chữ thường?
Bạn có thể sử dụng phương thức toUpperCase()
hoặc toLowerCase()
:
String str = "Hello World"; String upperStr = str.toUpperCase(); // Kết quả là "HELLO WORLD" String lowerStr = str.toLowerCase(); // Kết quả là "hello world"
4.15 Làm thế nào để thay thế các ký tự trong chuỗi bằng một ký tự khác?
Phương thức replace()
được sử dụng để thay thế các ký tự hoặc chuỗi con:
String str = "hello"; String newStr = str.replace('l', 'p'); // Kết quả là "heppo"
Bạn cũng có thể sử dụng replaceAll()
để thay thế bằng biểu thức chính quy (regex).
4.16 Cách kiểm tra nếu một chuỗi chứa chuỗi con trong Java?
Sử dụng phương thức contains()
để kiểm tra nếu một chuỗi chứa chuỗi con:
String str = "Hello World"; if (str.contains("World")) { System.out.println("Chuỗi chứa 'World'"); }
4.17 Sự khác biệt giữa String.intern()
và String pool?
intern()
là một phương thức của String
được sử dụng để đảm bảo rằng chuỗi hiện tại nằm trong String pool. Nếu chuỗi đã có trong pool thì nó sẽ trả về tham chiếu của chuỗi trong pool. Nếu không có, nó sẽ thêm chuỗi đó vào pool.
4.18 Sự khác biệt giữa equals()
và compareTo()
trong String
là gì?
equals()
kiểm tra xem hai chuỗi có bằng nhau về mặt nội dung hay không.compareTo()
so sánh thứ tự từ điển giữa hai chuỗi. Nếu chuỗi đầu tiên lớn hơn chuỗi thứ hai thì nó sẽ trả về giá