Làm thế nào một chuỗi có thể được khởi tạo bằng cách sử dụng?


154

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?


25
Chuỗi là một lớp VIP. " "đã là một chuỗi!
johnchen902

2
Không có ý nghĩa đặc biệt. Tôi chỉ có nghĩa là rất quan trọng. Đó là, java.lang.Stringcó sự đối xử đặc biệt của Ngôn ngữ Java.
johnchen902

16
Ai nói chuỗi đó là "một lớp như bất kỳ ai khác"? Đó là một lớp học rất đặc biệt, không giống bất kỳ ai khác. Vì giả sử của bạn là sai, nên câu hỏi không thực sự có thể trả lời được.
Eric Lippert

5
Chỉ vì giả sử là sai, điều đó không có nghĩa là câu hỏi không thể trả lời được. Và câu trả lời đúng đã có 197 phiếu.
Koray Tugay

Câu trả lời:


293

Chuỗi Java là đặc biệt

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

nhập mô tả hình ảnh ở đây

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ữ. Stringcác đối tượng được phân bổ thông qua toán tử mới được lưu trữ trong heapvà không có chia sẻ lưu trữ cho cùng một nội dung.


72
Lưu ý rằng "nhóm chung" thường là một phần của đống.
Joachim Sauer

3
@JoachimSauer Có..với những lợi ích nhỏ :) đã thêm vào đó trong ghi chú. Cảm ơn bạn đã ghi nhớ.
Suresh Atta

2
Vì vậy, nó nhanh hơn để viết String s1 = "Hello"; hơn Chuỗi s2 = Chuỗi mới ("Xin chào");?
dùng2097804

28
Tôi muốn thêm rằng trong ví dụ của bạn s1 == s2 == s3 nhưng s4! = S5
Alfredo Osorio

8
@AndrewJanke trên hotspot jvm gần đây (7), nhóm chuỗi không có trong gen perm và từ Java 8 không còn gen perm nữa ...
assylias

50

Java coi String là một lớp đặc biệt, bạn có thể khởi tạo theo cả hai cách

  1. Giao trực tiếp bằng chữ

    String a = "adsasdf";
  2. 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 poolvà 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ị.


18

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.


1
Tôi cũng không nhận thức được rằng "loại null" là một loại thích hợp trong Java. Thông tin rất hữu ích của nó, bạn nên tăng kích thước phông chữ.
Grijesh Chauhan

1
@GrijeshChauhan: tốt, "loại null" chỉ là từ ngữ tiện lợi để cho phép bất kỳ 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.
Joachim Sauer

15

Đây là một tính năng của ngôn ngữ Java. Chuỗi ký tự trong mã nguồn được xử lý đặc biệt.

Thông số ngôn ngữ, ở đây , chỉ đơn giản nói rằng một chuỗi ký tự là Stringloại


5

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.


4

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());
    }

Nếu bạn chỉ có thể khởi tạo một chuỗi với 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.
AJMansfield

Đó là không đúng. Một chuỗi ký tự chỉ là một chuỗi ký tự trong một tệp nguồn có nguồn gốc từ dấu ngoặc kép. Java tự động tạo một thể hiện của một chuỗi bằng cách sử dụng chữ này. Do đó, một đối tượng theo nghĩa đen và chuỗi bằng nhau, nhưng chúng không giống nhau. Java cũng có thể được triển khai theo cách này mà bạn phải sử dụng Chuỗi mới (""); để khởi tạo một đối tượng String, nhưng điều này chỉ khiến cuộc sống của chúng ta trở nên khó khăn hơn. Vì vậy, khi bạn viết Chuỗi mới ("một chuỗi"), java sẽ tạo một đối tượng Chuỗi cho chữ "một chuỗi" theo nghĩa đen và chuyển đối tượng chuỗi này đến trình kết hợp của Chuỗi mới.
Liên kết René

2

Chỉ cần đề cập đến. Một chuỗi ký tự là một tham chiếu đến một thể hiện của lớp Chuỗi, bạn có thể viết mã như thế này:

 "abc" .getBytes ();

 "a: b: c" .split (":");

 "" .CodePointAt (0);

2

- 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 newtừ 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ự.


2

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: -


2
Quá trình bạn mô tả không phải là những gì Java thực sự làm: Như những người khác đã nêu, "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.5JVMS §5.1 .
siegi

1

Java.lang.Stringkhô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, ...


5
""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).
g00glen00b

Tôi cập nhật câu trả lời của tôi. Có phải mọi người sử dụng điều này cho lợi thế của họ, như sử dụng các hằng chuỗi như tương đương với loại biểu tượng Lisp?
Sylwester
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.