2013-01-07 8 views
8
class StringTesting { 
    public static void main(String args[]) 
    { 
     String str = "abcd"; 
     String str1 = new String("abcd"); 
     String str2 = str.substring(0,2); 
     String str3 = str.substring(0,2); 
     String str4 = str.substring(0,str.length()); 
     String str5 = str1.substring(0,2); 
     String str6 = str1.substring(0,2); 
     String str7 = str1.substring(0,str1.length()); 

     System.out.println(str2 == str3); 
     System.out.println(str == str4); 
     System.out.println(str5 == str6); 
     System.out.println(str1 == str7); 
    } 
} 

Đây là kết quả tôi nhận được trên java 1.6.0_27:Java lưu trữ Strings như thế nào và chuỗi con hoạt động như thế nào?

false 
true 
false 
true 

Ai đó có thể xin giải thích đầu ra. Tôi biết Java phân biệt giữa String được lưu trữ trong heap và String được lưu trữ trong String "common pool" (có thể được interned). Nội bộ, đại diện của họ khác nhau như thế nào. Làm thế nào nó thay đổi thuật toán chuỗi con. Vui lòng trích dẫn sách/bài viết/blog, v.v. ở bất kỳ nơi nào phù hợp.

+0

Đó là nhiều câu hỏi. Và nó thậm chí sẽ không phải là câu trả lời tương tự cho JDK gần đây và cũ. –

+4

Nếu bạn thực sự muốn biết cách hoạt động, hãy đọc nguồn. Bạn sẽ không được tham khảo tốt hơn. Lưu ý: điều này đã được thay đổi trong bản cập nhật Java 7 6.;) –

+0

@dystroy: Đó là lý do tại sao tôi đã đưa ra phiên bản Java của mình trong câu hỏi. Tôi không nhớ một câu trả lời cho JDK cũ hoặc gần đây. – Bruce

Trả lời

21

Xem các ý kiến:

String str = "abcd"; // new String LITERAL which is interned in the pool 
    String str1 = new String("abcd"); // new String, not interned: str1 != str 
    String str2 = str.substring(0,2); // new String which is a view on str 
    String str3 = str.substring(0,2); // same: str3 != str2 
    String str7 = str1.substring(0,str1.length()); // special case: str1 is returned 

Ghi chú:

  • Kể từ Java 7u6, chuỗi trả về một chuỗi mới thay vì chế độ xem trên chuỗi gốc (nhưng điều đó không tạo sự khác biệt cho ví dụ đó)
  • Trường hợp đặc biệt khi bạn gọi str1.substring(0,str1.length()); - xem mã:

    public String substring(int beginIndex, int endIndex) { 
        //some exception checking then 
        return ((beginIndex == 0) && (endIndex == value.length)) ? this 
          : new String(value, beginIndex, subLen); 
    } 
    

EDIT

một cái nhìn như thế nào?

Cho đến Java 7u6, một String cơ bản là một char[] có chứa các ký tự của chuỗi với một bù đắp và một số (ví dụ: chuỗi gồm count ký tự bắt đầu từ vị trí offset trong char[]).

Khi gọi chuỗi con, một chuỗi mới sẽ được tạo với cùng một số char[] nhưng khác nhau/số đếm, để tạo hiệu quả chế độ xem trên chuỗi gốc. (Trừ khi đếm = chiều dài và bù đắp = 0 như đã giải thích ở trên).

Vì java 7u6, một char[] mới được tạo ra mọi lúc, bởi vì không còn trường nào khác là count hoặc offset trong lớp chuỗi.

Bể bơi chung được lưu trữ ở đâu?

Đây là triển khai cụ thể. Vị trí của hồ bơi đã thực sự di chuyển trong các phiên bản gần đây. Trong các phiên bản gần đây, nó được lưu trữ trên heap.

Bể bơi được quản lý như thế nào?

Các đặc điểm chính:

  • literals chuỗi được lưu trữ trong hồ bơi
  • chuỗi thực tập nội trú được lưu trữ trong hồ bơi (new String("abc").intern();)
  • Khi một chuỗi S được thực tập nội trú (vì nó là một chữ hoặc bởi vì intern() được gọi), JVM sẽ trả về một tham chiếu đến một chuỗi trong hồ bơi nếu có một tham chiếu là equals đến S (do đó "abc" == "abc" nên al cách trở lại đúng).
  • Strings trong hồ bơi có thể được thu thập rác (có nghĩa là một chuỗi thực tập nội trú có thể được loại bỏ khỏi hồ bơi tại một số sân khấu nếu nó trở nên đầy đủ)
+0

Chế độ xem là gì và hồ bơi chung được lưu trữ chính xác ở đâu và được quản lý như thế nào? – Bruce

+0

@Bruce xem các chỉnh sửa của tôi. – assylias

+0

Cảm ơn. Câu trả lời chính xác! – Bruce

1

String là đối tượng không thay đổi.

String#subString - tạo chuỗi mới. Source

Trong mã nó là [mở jdk 6] -

public String substring(int beginIndex, int endIndex) { 
    if (beginIndex < 0) { 
     throw new StringIndexOutOfBoundsException(beginIndex); 
    } 
    if (endIndex > value.length) { 
     throw new StringIndexOutOfBoundsException(endIndex); 
    } 
    int subLen = endIndex - beginIndex; 
    if (subLen < 0) { 
     throw new StringIndexOutOfBoundsException(subLen); 
    } 
    return ((beginIndex == 0) && (endIndex == value.length)) ? this 
      : new String(value, beginIndex, subLen); 
} 
+1

'chuỗi con' không bao giờ tạo đối tượng mới trong nhóm chuỗi ký tự, nhưng nó có thể trả lại cùng một đối tượng đã có trong nhóm chuỗi ký tự. –

+0

Nguồn - Tôi đã kiểm tra nguồn [link] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java#String.substring % 28int% 2Cint% 29) –

+1

@Quoi Nguồn hiển thị rằng một chuỗi mới được tạo, không có trong chuỗi chuỗi ... – assylias