2012-06-23 44 views
5

Trong Java, rõ ràng, String s = "foo" được ưu tiên hơn String s = new String("foo").Tại sao tôi không thể khởi tạo một đối tượng chuỗi với một hàm tạo?

Tại sao? Không phải là một đối tượng chuỗi mới được tạo trong cả hai trường hợp? Tại sao trường hợp đầu tiên ngăn cản việc gọi một nhà xây dựng?

+0

thể trùng lặp của [sự khác biệt giữa "văn bản" và new String ("text") là gì trong Java?] (http://stackoverflow.com/questions/3052442/what-is-the-difference-between-text-and-new-stringtext-in-java). (Một khi bạn hiểu sự khác biệt giữa hai hình thức, rõ ràng là tại sao đầu tiên được ưa thích ... trong hầu hết các trường hợp.) –

Trả lời

9

Tại sao?

Vì phương pháp thứ hai dẫn đến hai đối tượng chuỗi đối tượng chuỗi (ban đầu do chuỗi ký tự, cộng với bản sao rõ ràng).

+0

Cách tiếp cận thứ hai dẫn đến hai đối tượng chuỗi - chỉ khi "foo" chưa có trong nhóm String . –

+0

@KazekageGaara, để tham khảo '" foo "' nó phải ở trong "hồ bơi" rồi. Nó được khai báo trong nhóm hằng số của lớp và nó được đặt ở đó trong khi lớp (hoặc phương thức cụ thể) được JVM xử lý – bestsss

1

Tôi không nghĩ là thích hợp hơn. Tôi cho rằng "lợi ích" duy nhất bạn nhận được là nếu bạn sử dụng sai "==" toán tử thay cho phương thức equals, có hai trường hợp khác nhau của một chuỗi sẽ thất bại nhanh hơn và sẽ nhắc bạn sửa mã của bạn. (Toán tử == thể "thành công" và thất bại không lường trước được)

Trừ khi tất nhiên mã của bạn đòi hỏi bạn để xây dựng hai trường hợp khác nhau vì lý do gì

+0

Yêu cầu hai trường hợp khác nhau của một chuỗi 'String' (có nội dung giống hệt nhau) . "trường hợp" của một 'int' ... có lẽ có một số bản đồ người nghèo lạm dụng một nơi nào đó ... nhưng tôi hy vọng không: -/ –

+0

Có, với thực tế là String là bất biến, tôi không thể nghĩ ra bất kỳ lý do tại sao bất cứ ai sẽ yêu cầu một điều như vậy.Đó là lý do tại sao tôi nói "vì lý do gì" –

4

Trường hợp đầu tiên là một chuỗi chữ , chỉ cần một viết tắt ngôn ngữ cung cấp cho bạn để tạo ra một chuỗi. Trình tạo lớp String vẫn được gọi, không rõ ràng, có nghĩa là ít đánh máy hơn và ít lộn xộn hơn.

Trường hợp thứ hai lấy đối tượng String đã được tạo bởi chữ và chuyển nó tới một hàm tạo, sao chép nội dung để tạo một đối tượng String mới, riêng biệt. Các chữ sẽ vẫn được xung quanh bởi vì literals được interned. Có rất ít điểm để sử dụng hàm tạo String (khá nhiều khi bạn đã tạo một chuỗi con của một chuỗi rất lớn và muốn giải phóng bộ nhớ được sử dụng bởi phần còn lại của chuỗi, bởi vì các giá trị mặc định sử dụng cùng char mảng cơ bản là chuỗi gốc, chỉ với một offset và độ dài khác nhau.

+0

điểm nhỏ: * Chữ sẽ vẫn ở xung quanh vì các chữ được tập trung. *, Nếu chữ không có tham chiếu đến (như đang ở trong nhóm không đổi của lớp) thì tự do là GC 'd, có hiệu quả giải phóng perm-gen (miễn là JVM sử dụng perm-gen, một số không) – bestsss

+0

@bestsss: Nhưng không phải là chữ luôn luôn là một phần của hồ bơi không đổi? –

+1

Các hồ bơi liên tục là một phần của lớp học của nó. Chuỗi được khai báo ra khỏi nhóm không đổi đi đến perm-gen (dưới Suns JVM, một số JVM không sử dụng perm-gen). Nhưng sau khi class + classloader là GC'd, JVM cũng được tự do "miễn phí" instance nội trú. Nếu không, tất cả các tên, chữ, v.v ... sẽ bị rò rỉ sau khi 'undeploy'/'redeploy' – bestsss

1

tại sao? không phải là một đối tượng chuỗi mới được tạo ra trong cả hai trường hợp?

không, hình thức ban đầu là một chuỗi chữ sẽ được thực tập nội trú như vậy mà chỉ một trường hợp được tạo ra:

String s = "foo"; 
String s2 = "foo"; 

s == s2 => true

Các vấn đề liên quan