2009-12-11 36 views
5
public static void main(String [] a) 
{ 
    String s = new String("Hai"); 
    String s1=s; 
    String s2="Hai"; 
    String s3="Hai"; 
    System.out.println(s.hashCode()); 
    System.out.println(s1.hashCode()); 
    System.out.println(s2.hashCode()); 
    System.out.println(s3.hashCode()); 
    System.out.println(s==s2); 
    System.out.println(s2==s3); 

} 

Từ mã trên, bất kỳ ai cũng có thể giải thích điều gì sẽ xảy ra sau khi JVM gặp phải dòng này (s == s2)?Cách "==" hoạt động cho các đối tượng?

Trả lời

17

So sánh tham chiếu - tức là cả hai biến đều đề cập đến cùng một đối tượng chính xác (thay vì chỉ các đối tượng bằng nhau).

  • ss2 tham chiếu đến các đối tượng khác nhau, do đó biểu thức đánh giá là sai.
  • ss1 tham chiếu đến cùng một đối tượng (giống nhau) do bài tập.
  • s2s3 đề cập đến cùng một đối tượng (như nhau) vì chuỗi thực tập.

Nếu điều đó không giúp được gì nhiều, vui lòng hỏi thêm chi tiết về một bit cụ thể. Các đối tượng và tham chiếu có thể gây nhầm lẫn khi bắt đầu.

Lưu ý rằng chỉ có chuỗi literals đang thực tập nội trú theo mặc định ... do đó, mặc dù ss2 tham khảo bằng chuỗi, họ vẫn còn hai đối tượng riêng biệt. Tương tự, nếu bạn viết:

String x = new String("foo"); 
String y = new String("foo"); 

thì x == y sẽ đánh giá là sai. Bạn có thể lực interning, mà trong trường hợp này sẽ thực sự trở lại với nghĩa đen thực tập nội trú:

String x = new String("foo"); 
String y = new String("foo"); 
String z = "foo"; 

// Expressions and their values: 
x == y: false 
x == z: false 
x.intern() == y.intern(): true 
x.intern() == z: true 

EDIT: Một bình luận cho rằng new String(String) về cơ bản là vô nghĩa. Đây không phải là trường hợp, trên thực tế.

A String đề cập đến một char[], có độ lệch và chiều dài. Nếu bạn lấy một chuỗi con, nó sẽ tạo một Chuỗi mới đề cập đến cùng một sốchar[], chỉ với độ dài và độ lệch khác nhau. Nếu bạn cần giữ một chuỗi con nhỏ của chuỗi dài trong một thời gian dài, nhưng chính chuỗi dài không cần thiết, thì việc sử dụng công cụ tạo new String(String) để tạo một bản sao chỉ là phần bạn cần, cho phép lớn hơn char[] để được thu gom rác thải.

Ví dụ về việc này là đọc một tệp từ điển - nhiều từ ngắn, một từ trên mỗi dòng. Nếu bạn sử dụng BufferedReader.readLine(), mảng char được phân bổ sẽ có ít nhất 80 ký tự (trong JDK chuẩn). Điều đó có nghĩa rằng ngay cả một từ ngắn như "và" có một mảng char của 160 byte + overheads ... bạn có thể chạy ra khỏi không gian khá nhanh chóng như vậy. Sử dụng new String(reader.readLine()) có thể tiết kiệm trong ngày.

+1

Không phải là các chuỗi được thực tập, vì vậy nó thực sự đánh giá đúng? –

+3

@Winston Smith: Các chữ được tập trung, nhưng 's' được gán giá trị trả về của một cuộc gọi hàm tạo. –

+0

@Winston: Nếu chúng là cùng một đối tượng, nhưng bạn sẽ thấy một cuộc gọi đến intern() trong câu hỏi ở đâu? – Fredrik

1

== đối tượng tổng hợp không phải nội dung của đối tượng. s và s2 là các đối tượng khác nhau. Nếu bạn muốn so sánh nội dung, hãy sử dụng s.equals (s2).

+0

có thể cụ thể hơn, vì tôi biết nó không so sánh nội dung. – Hariharbalaji

-3

Bạn đang sử dụng một số '==' quá tải cho lớp Chuỗi ...

+0

-1: Java không có quá tải toán tử. –

+0

um, ngoại trừ + trên chuỗi Tôi đoán :-) –

0

Nó phải là một hiển nhiên sai. JVM làm một việc như sử dụng các chuỗi tồn tại trong bộ nhớ. Do đó s2, s3 trỏ đến cùng một Chuỗi đã được khởi tạo một lần. Nếu bạn làm một cái gì đó giống như s5 = "Hải" ngay cả đó sẽ bằng s3.

Tuy nhiên, mới tạo đối tượng mới. Không phân biệt nếu String đã được exisitng hay không. Do đó s doesnot bằng s3, s4.

Bây giờ, nếu bạn làm s6 = new String ("Hai"), ngay cả khi đó sẽ không bằng s2, s3 hoặc s.

1

Tôi giả sử bạn biết rằng khi bạn kiểm tra sự bình đẳng giữa các biến sử dụng '==', bạn đang thực sự kiểm tra xem các tham chiếu trong bộ nhớ có giống nhau hay không. Điều này khác với phương thức equals() kết hợp một thuật toán và các thuộc tính để trả về một kết quả cho biết hai đối tượng được coi là giống nhau. Trong trường hợp này, nếu kết quả là đúng, nó thường có nghĩa là cả hai tham chiếu đều trỏ đến cùng một đối tượng. Điều này khiến tôi tự hỏi tại sao s2 == s3 trả về true và liệu các cá thể String (không thay đổi) được gộp lại để tái sử dụng ở đâu đó.

+2

Đối tượng chuỗi được tạo theo yêu cầu. Nếu một String đã tồn tại các điểm tham chiếu mới cho cùng một đối tượng hơn là tạo một đối tượng chuỗi mới. Xem câu trả lời của tôi dưới đây. Tuy nhiên, câu lệnh không áp dụng cho các đối tượng được tạo bằng String mới(). – Geek

+1

Cảm ơn lời giải thích. Vì vậy, nếu tôi làm điều này: Chuỗi s1 = Chuỗi mới ("một chuỗi"); Chuỗi s2 = chuỗi mới ("chuỗi"); s1 và s2 trỏ đến cùng một trường hợp?Tôi giả định ở đây rằng việc phân bổ String tương đương với việc bạn có thể khởi tạo một String một cách rõ ràng hay sử dụng autoboxing. –

+0

À phải rồi, giờ tôi hiểu rồi. Nếu bạn sử dụng một String mới(), bạn buộc phải tạo một cá thể mới. Đó là loại trò đố bạn có thể rút ra tại cuộc phỏng vấn xin việc. –

1
Think of it like this. 
    Identical twins look the same but they are made up differently. 
If you want to know if they "look" the same use the compare. 
If you want to know they are a clone of each other use the "==" 

:) 
1

== so sánh vị trí bộ nhớ (tham chiếu) của Object s. Bạn nên sử dụng .equals() để so sánh nội dung của đối tượng.

Bạn có thể sử dụng == cho int s và double s, vì họ là các kiểu dữ liệu nguyên thủy

0

Các literals s2 và s3 sẽ trỏ đến cùng một chuỗi trong bộ nhớ khi họ có mặt tại thời gian biên dịch. s được tạo ra trong thời gian chạy và sẽ trỏ đến một thể hiện khác của "Hai" trong bộ nhớ. Nếu bạn muốn s trỏ đến cùng một ví dụ của "Hai" là s2 và s3, bạn có thể yêu cầu Java thực hiện điều đó cho bạn bằng cách gọi thực tập. Vì vậy, s.intern == s2 sẽ là sự thật.

Bài viết hay here.

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