Nếu String là một lớp giống như bất kỳ lớp nào khác, làm thế nào nó có thể được khởi tạo bằng dấu ngoặc kép?
java.lang.String
có sự đối xử đặc biệt của Ngôn ngữ Java.
Nếu String là một lớp giống như bất kỳ lớp nào khác, làm thế nào nó có thể được khởi tạo bằng dấu ngoặc kép?
java.lang.String
có sự đối xử đặc biệt của Ngôn ngữ Java.
Câu trả lời:
Các nhà thiết kế của Java đã quyết định giữ lại các kiểu nguyên thủy trong một ngôn ngữ hướng đối tượng, thay vì biến mọi thứ thành một đối tượng, để cải thiện hiệu suất của ngôn ngữ. Nguyên thủy được lưu trữ trong ngăn xếp cuộc gọi, đòi hỏi ít không gian lưu trữ hơn và rẻ hơn để thao tác. Mặt khác, các đối tượng được lưu trữ trong heap chương trình, đòi hỏi quản lý bộ nhớ phức tạp và nhiều không gian lưu trữ hơn.
Vì lý do hiệu năng, Chuỗi của Java được thiết kế ở giữa lớp nguyên thủy và lớp.
Ví dụ
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
Lưu ý: Chuỗi ký tự được lưu trữ trong một nhóm chung. Điều này tạo điều kiện chia sẻ lưu trữ cho các chuỗi có cùng nội dung để bảo tồn lưu trữ. String
các đối tượng được phân bổ thông qua toán tử mới được lưu trữ trong heap
và không có chia sẻ lưu trữ cho cùng một nội dung.
Java coi String là một lớp đặc biệt, bạn có thể khởi tạo theo cả hai cách
Giao trực tiếp bằng chữ
String a = "adsasdf";
Như các Đối tượng khác sử dụng từ khóa mới
String a = new String("adsasdf");
Bạn cần đặc biệt cẩn thận khi muốn so sánh với ==
dấu hiệu:
String a = "asdf";
String b = "asdf";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b); // False
System.out.println(a.equals(b)); // True
Đó là bởi vì trong trường hợp đầu tiên, các đối tượng a và b được giữ trong một cái gì đó được gọi literal pool
và cả hai đều tham chiếu cùng một đối tượng để chúng bằng nhau theo cả hai cách.
Nhưng trong trường hợp thứ hai, a và b tham chiếu các đối tượng khác nhau như khi chúng ta khởi tạo bất kỳ đối tượng nào khác. do đó chúng không bằng nhau khi so sánh với ==
toán tử trong khi chúng bằng nhau về giá trị.
Chuỗi được xử lý đặc biệt trong JLS: đó là một trong hai loại không nguyên thủy tồn tại theo nghĩa đen (loại kia là Class
) * .
Từ JLS :
Một chuỗi ký tự là một tham chiếu đến một thể hiện của lớp `String [...].
* tốt, cũng có "loại null" với "loại không có nghĩa đen" null
, nhưng hầu hết mọi người không nghĩ "loại null" là một loại thích hợp.
null
được gán cho bất kỳ biến loại tham chiếu nào. Nó không phải là một loại thú vị, nếu không.
Văn bản bên trong dấu ngoặc kép tạo ra một String
đối tượng theo nghĩa đen .
String myString = "Some text";
Đoạn mã trên tạo ra một String
đối tượng, sử dụng dấu ngoặc kép.
Chuỗi rất thường được sử dụng trong một ngôn ngữ lập trình. Vì java là đối tượng hướng nên một chuỗi là một đối tượng. Để tránh Chuỗi mới rườm rà ("someString"); câu lệnh mỗi khi bạn cần một đối tượng chuỗi java cho phép bạn chỉ cần tạo một đối tượng chuỗi bằng cách sử dụng chuỗi ký tự.
Nhưng bạn nên ghi nhớ sự bình đẳng chuỗi. Đây là một bài kiểm tra JUnit ngắn để chứng minh điều tôi muốn nói.
@Test
public void stringTest() {
// a string literal and a string object created
// with the same literal are equal
assertEquals("string", new String("string"));
// two string literals are the same string object
assertSame("string", "string");
// a string literal is not the same object instance
// as a string object created with the same string literal
assertFalse("string" == new String("string"));
// java's String.intern() method gives you the same
// string object reference for all strings that are equal.
assertSame("string", new String("string").intern());
}
new String(String src)
, thì bạn thậm chí sẽ không thể cung cấp cho hàm tạo một chuỗi ký tự. Bạn sẽ phải khởi tạo một char []
, và sau đó sử dụng bộ phối âm String(char [] src)
để xây dựng chuỗi hoặc bạn sẽ phải đọc chuỗi từ một tệp.
- Chuỗi là một lớp trong Java . Bạn đã đúng về nó, vì vậy chúng tôi luôn có thể khởi tạo với new
từ khóa.
- Nhưng khi chúng ta làm một cái gì đó như:
String s = "";
Câu lệnh trên được trình biên dịch đánh dấu là một đối tượng Chuỗi đặc biệt và sau đó là JVM trong khi tải lớp (tải được thực hiện trước khi khởi tạo), xem đây là cái được gọi là chuỗi ký tự , được lưu trữ trong nhóm chuỗi ký tự .
- Vì vậy, một Chuỗi có thể được tạo bằng cách sử dụng new()
và theo ""
phương thức, nhưng chuỗi sau cung cấp một chuỗi ký tự chuỗi nằm trong heap ngay cả khi không có tham chiếu đến đối tượng chuỗi đó, bởi vì nó có tham chiếu từ nhóm chuỗi ký tự.
Java thực hiện quy trình hai bước cho chúng tôi.
String str = "hello";
tương đương với
char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);
Giống như [.NET] [1] có một điều tương tự.
String(Char[]) constructor
làm
String(char[] value)
Thêm tài liệu tham khảo: -
"hello"
là một chuỗi ký tự và sẽ được trình biên dịch đưa vào nhóm hằng số, xem JLS §3.10.5 và JVMS §5.1 .
Java.lang.String
không chỉ là một lớp học. Đó là một phần không thể thiếu của ngôn ngữ cốt lõi. Trình biên dịch có cú pháp đường cho nó. Ví dụ, ""
giống như một từ viết tắt cho new String("")
. Khi được viết ""
, trình biên dịch sẽ tối ưu hóa các chuỗi giống hệt nhau cho cùng một thể hiện để tiết kiệm không gian."a" + 5 == "a5" ==> true
Trình biên dịch có đường cú pháp cho rất nhiều thứ, bao gồm không phải đóng hộp / bỏ hộp giữa các phiên bản đối tượng và các kiểu gốc của chúng, không có cha mẹ có nghĩa là Object, hàm tạo mặc định, ...
""
không phải là viết tắt cho new String("")
. Nếu bạn sử dụng ""
, điều đầu tiên sẽ được thực hiện là tìm kiếm các kết quả khớp trong nhóm Chuỗi của JVM và nếu điều đó là đúng, nó sẽ trả về Chuỗi đó. Bằng cách sử dụng new String("")
, bạn sẽ luôn tạo một Chuỗi mới, ngay cả khi chính Chuỗi đã tồn tại trong nhóm Chuỗi (vì nó sẽ không được lưu trữ trong nhóm Chuỗi).
" "
đã là một chuỗi!