27

sự khác biệt giữa 2 mã này là gì:Java vượt qua bằng cách tham khảo

Mã A:

Foo myFoo; 
myFoo = createfoo(); 

nơi

public Foo createFoo() 
{ 
    Foo foo = new Foo(); 
    return foo; 
} 

Vs. Mã B:

Foo myFoo; 
createFoo(myFoo); 

public void createFoo(Foo foo) 
{ 
    Foo f = new Foo(); 
    foo = f; 
} 

Có sự khác biệt nào giữa 2 đoạn mã này không?

+7

Không có "chuyển bằng tham chiếu" ở đó. Nó vượt qua bởi giá trị, và giá trị là một tham chiếu. Mã B không biên dịch, và nếu nó sẽ không thay đổi myFoo. – harold

Trả lời

165

Java luôn chuyển đối số theo giá trị NOT theo tham chiếu.


Hãy để tôi giải thích điều này thông qua một example:

public class Main 
{ 
    public static void main(String[] args) 
    { 
      Foo f = new Foo("f"); 
      changeReference(f); // It won't change the reference! 
      modifyReference(f); // It will modify the object that the reference variable "f" refers to! 
    } 
    public static void changeReference(Foo a) 
    { 
      Foo b = new Foo("b"); 
      a = b; 
    } 
    public static void modifyReference(Foo c) 
    { 
      c.setAttribute("c"); 
    } 
} 

tôi sẽ giải thích điều này trong các bước:

  1. Tuyên bố một tài liệu tham khảo tên f loại Foo và gán nó vào một mới đối tượng thuộc loại Foo với thuộc tính "f".

    Foo f = new Foo("f"); 
    

    enter image description here

  2. Từ phía phương pháp, một tài liệu tham khảo của loại Foo với một tên a được khai báo và nó ban đầu được giao cho null.

    public static void changeReference(Foo a) 
    

    enter image description here

  3. Như bạn gọi phương thức changeReference, tài liệu tham khảo a sẽ được giao cho các đối tượng được thông qua như là một cuộc tranh cãi.

    changeReference(f); 
    

    enter image description here

  4. Tuyên bố một tài liệu tham khảo tên b loại Foo và gán nó vào một đối tượng mới của loại Foo với một thuộc tính "b".

    Foo b = new Foo("b"); 
    

    enter image description here

  5. a = b được tái gán tham chiếu a KHÔNG f đến đối tượng có thuộc tính của nó là "b".

    enter image description here


  6. Như bạn gọi modifyReference(Foo c) phương pháp, một tham chiếu c được tạo ra và gán cho đối tượng với thuộc tính "f".

    enter image description here

  7. c.setAttribute("c"); sẽ thay đổi các thuộc tính của đối tượng tham chiếu c điểm với nó, và nó cùng một đối tượng tham chiếu f điểm đến nó.

    enter image description here

Tôi hy vọng bạn hiểu bây giờ như thế nào đi qua đối tượng như các đối số làm việc trong Java :)

+15

Giải thích TUYỆT VỜI! Tôi cảm thấy chứng ngộ! – delita

+10

Bò thánh. Điều này đã được hỏi và trả lời nhiều lần, nhưng đây là giải pháp phức tạp và nghệ thuật nhất mà tôi từng thấy. Bravo! – duffymo

+0

Bạn có thể tương phản với nội dung "truyền bằng tham chiếu" không? Điều gì có ý nghĩa với tôi là với "truyền theo giá trị", nó đi qua địa chỉ bộ nhớ của đối tượng được tham chiếu bởi f. Trong ** changeReference **, ** a ** là biến mới đề cập đến cùng một địa chỉ bộ nhớ, việc thay đổi giá trị ** a ** (hoặc được nhắc đến địa chỉ bộ nhớ) chỉ thay đổi ** ** điểm nào thành và không ** f **. Nếu nó được "chuyển qua tham chiếu" ** f ** sẽ được chuyển vào vì vậy ** a = f **, thay đổi giá trị ** a ** (hoặc địa chỉ bộ nhớ tham chiếu) sẽ thay đổi ** f ** –

8

Vì Java hoàn toàn "chuyển giá trị" và thậm chí tham chiếu đến đối tượng được truyền theo giá trị, mã thứ hai sẽ không hoạt động như mong đợi. Xem phần "Liên quan" ở bên phải để xem nhiều sự kiện thảo luận về điều này.

2

Hãy suy nghĩ về các thông số phương pháp như biến riêng tờ khai của họ. Nếu bạn đã thay thế các cuộc gọi phương pháp với một khối duy nhất của mã này, nó trông như thế này:

Foo myFoo; 
{      //Method call starts here 
    Foo foo; 
    foo = myFoo; 
    Foo f = new Foo(); 
    foo = f; 
}      //Method call ends here 

Thậm chí nếu tham số phương pháp có tên giống như một biến khác, tham số phương pháp vẫn là riêng của nó, tham chiếu duy nhất mà chỉ có phương pháp biết. Đó là điều tương tự mà Eng.Fouad đã nói ở trên.

1

Một điểm quan trọng khác mà bạn nên biết là loại đối tượng mà bạn chuyển vào phương thức. cho dù đó là một đối tượng có thể thay đổi hoặc một đối tượng bất biến. Nếu bạn truyền một đối tượng bất biến như String, nó sẽ tạo một bản sao khác và thực hiện sửa đổi. Các thay đổi không được phản ánh cho bản gốc của bạn.

+0

Không, không có khái niệm "có thể thay đổi" hoặc "bất biến" trong ngôn ngữ. Do đó, không có sự khác biệt trong cách chúng được thông qua. "Các thay đổi không được phản ánh cho bản gốc của bạn". Một đối tượng bất biến, theo định nghĩa, là một đối tượng không có phương thức để "thay đổi", do đó, câu lệnh này không có ý nghĩa. – newacct

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