2013-02-16 20 views
6

Hi Im học tập cho kỳ thi scja của tôi và có một câu hỏi về chuỗi đi qua ref/value và cách chúng không thay đổi. Đoạn mã sau xuất ra "abc abcfg".Java String không thay đổi được thông qua tham chiếu/giá trị

Điều tôi muốn biết là tại sao điều này lại xảy ra? Im không hiểu những gì xảy ra bên trong phương thức f. Chuỗi được truyền theo giá trị vì vậy chắc chắn nó sẽ thay đổi thành "abcde" bên trong phương thức? Bởi vì nếu b + = "fg" gắn thêm vào chuỗi tại sao nó không hoạt động bên trong phương thức?

Cảm ơn!

public class Test { 

    public static void main(String[] args){ 
     String a =new String("abc"); 
     String b = a; 
     f(b); 
     b+="fg" 
     System.out.println(a + " " + b); 
    } 

    public static void f(String b){ 
     b+="de"; 
     b=null; 
    } 
} 
+1

Điều quan trọng cần nhớ là các tham chiếu được truyền theo giá trị. f lấy một bản sao của tham chiếu ban đầu là con trỏ tới "fg". –

Trả lời

2

Trong phương pháp của bạn f() bạn đang gán một String mới cho tham số b, nhưng thông số cũng giống như các biến địa phương, do đó gán một cái gì đó để chúng không ảnh hưởng đến bất cứ điều gì ngoài phương pháp này. Đó là lý do tại sao chuỗi bạn truyền vào không thay đổi sau khi gọi phương thức.

+0

vì vậy tôi sẽ phải làm b = f (b) và trả về một chuỗi từ phương thức f? –

+0

Chính xác! Thậm chí sau đó, cho đến khi bạn trả về chuỗi, không có hiệu ứng nào ngoài phương thức. – Bohemian

+0

Nó cũng chỉ ra rằng nếu bạn đã làm b = f (b) và trả về một String với mã hóa hiện tại của bạn, bạn sẽ được trái với đầu ra "abc nullfg", như bạn nói b = null. –

0

Khi bạn chuyển chuỗi vào phương thức, nó tạo đối tượng String mới trong phương thức. Nếu bạn đặt một tuyên bố println theo phương pháp của mình, như sau:

public static void f(String b){ 
    b+="de"; 
    System.out.println(b); 
    b=null; 
} 

Bạn sẽ thấy đầu ra "abcde".

Tuy nhiên, khi bạn thoát ra khỏi phương pháp, bạn quay lại đối tượng gốc của mình, đối tượng này chưa bị thay đổi. Do đó, việc thêm fg vào nó sẽ chỉ tạo ra một chuỗi MỚI (b), chứa "abcfg".

8

Dòng b+="de"; trong các chức năng void f(String b) tạo đối tượng hoàn toàn mới là String không ảnh hưởng đến đối tượng trong hàm main.

Vì vậy, khi chúng ta nói Stringbất biến khi bình bất kỳ thay đổi trên một đối tượng String sẽ cho kết quả trong việc tạo ra một đối tượng hoàn toàn mới String

public class Test { 
    public static void main(String[] args){ 
     String a =new String("abc"); 

     String b = a; // both a & b points to the same memory address 

     f(b); // has no effect 

     // b still has the value of "abc" 
     b+="fg" // a new String object that points to different location than "a" 

     System.out.println(a + " " + b); // should print "abc abcfg" 
    } 

public static void f(String b){ 
    b+="de"; // creates a new object that does not affect "b" variable in main 
    b=null; 
} 
} 
3

dòng mã này:

b += "de"; 

Dịch thô thành:

b = b + "de"; 

Tạo chuỗi mới và lưu trữ nó trong biến cục bộ 'b'. Các tham chiếu bên ngoài phương pháp này không được thay đổi trong anyway bằng cách này. Có một vài điều quan trọng cần nhớ khi cố gắng hiểu cách thức/tại sao điều này hoạt động theo cách này.

  1. Trong Java, tất cả đối số phương thức đều được chuyển theo giá trị.
  2. Phương thức có ngăn xếp cục bộ nơi tất cả dữ liệu của chúng được lưu trữ, bao gồm các đối số phương thức.

Khi gán một đối tượng mới cho biến được chuyển vào phương thức, bạn chỉ thay thế địa chỉ trong ngăn cục bộ, với địa chỉ của đối tượng mới được tạo. Địa chỉ đối tượng thực tế bên ngoài phương thức vẫn giữ nguyên.

0

bạn tạo một đối tượng mới của String khi bạn nói điều gì đó giống như b + = "de"

của nó giống như nói rằng b = new String (b + "de");

Nếu bạn thực sự muốn giữ lại giá trị thông qua năm sau đó sử dụng một StringBuilder như thế này:

StringBuilder a =new StringBuilder("abc"); 
     StringBuilder b = a; 
     f(b); 
     b.append("fg"); 
     System.out.println(a + " " + b); 
    } 

    public static void f(StringBuilder b){ 
     b.append("de"); 
     b=null; 
    } 

Bây giờ đầu ra của bạn sẽ là "abcdefg" vì đối tượng StringBuilder b đã được thông qua vào f là giá trị của đối tượng chinh no. Tôi đã sửa đổi giá trị mà không sử dụng "mới" để trỏ đến một đối tượng khác. Hy vọng rõ ràng của nó bây giờ.

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