2015-04-19 26 views
9

Có rất nhiều cuộc thảo luận trong stackoverflow liên quan đến việc truyền theo giá trị và chuyển qua tham chiếu. Nhưng tôi muốn biết điều gì đang xảy ra trong kịch bản sau đây? Trang này cho biết java được truyền theo giá trị. Is Java "pass-by-reference" or "pass-by-value"?.Danh sách chuyển Java sang các phương thức hoạt động như được chuyển qua tham chiếu

Trong trường hợp mã sau, phần tử được xóa khỏi phương thức removeElement, nó sẽ xóa phần tử thứ 5 khỏi danh sách khi tôi in danh sách.

public class Load { 
    public static void main(String[] args) { 


     ArrayList<Integer> list = new ArrayList<Integer>(); 
     list.addAll(Arrays.asList(1,1,2,3,5,5,13,21)); 
     removeElement(list); 
     System.out.println(list); 
    } 
     public static void removeElement(List<Integer> list){ 
      list.remove(5);//removes element at index 5 
     } 
} 

Đầu ra của chương trình là [1, 1, 2, 3, 5, 13, 21].

Ai đó có thể giải thích cách giá trị này vượt qua giá trị thay vì truyền theo tham chiếu?

+1

Không thể đây không phải là sự lừa đảo. –

+7

Trên thực tế, nói rằng Java là "pass-by-value" là không cần thiết gây nhầm lẫn, và nó đòi hỏi phải xoắn ý nghĩa bình thường của các từ tiếng Anh. Java có hai loại giá trị: kiểu nguyên thủy và kiểu tham chiếu (đối tượng và mảng). Đối với các kiểu nguyên thủy, giá trị được chuyển. Và đối với các loại tham chiếu, tham chiếu được chuyển. Một số người muốn thêm rằng tham chiếu này được chuyển "theo giá trị" nhưng điều đó không thêm bất kỳ điều gì vào sự hiểu biết của bất kỳ ai về chủ đề đó. Vì tham chiếu được chuyển cho các loại tham chiếu, bạn sẽ thấy các sửa đổi bạn thực hiện cho đối tượng trở lại trong trình gọi của phương thức. –

Trả lời

1

Mặc dù câu hỏi này yêu cầu (một lần nữa) cho sự khác biệt giữa "pass-by-value" và "pass-by-value", tôi nghĩ rằng có một quan niệm sai lầm cơ bản gây ra rất nhiều nhầm lẫn. Điều này phải được giải quyết:

Thực tế, cuộc gọi phương thức chuyển tất cả các thông số theo giá trị. Như Erwin Bolwidt chỉ ra trong ý kiến ​​của mình, có hai loại định dạng:

  • loại nguyên thủy
  • loại tài liệu tham khảo

Các JLS (§4) khẳng định nó:

Các ngôn ngữ lập trình Java là một ngôn ngữ được gõ tĩnh, có nghĩa là mọi biến và mọi biểu thức đều có một kiểu được biết tại thời gian biên dịch.
[...]
Có hai loại loại trong ngôn ngữ lập trình Java: kiểu nguyên thủy (§4.2) và loại tham chiếu (§4.3).

Khi nói về "giá trị theo giá trị", điều đó có nghĩa là nội dung của biến được chuyển theo giá trị khi được sử dụng làm thông số cho cuộc gọi phương thức. Và nội dung của biến tham chiếu đã nhập là tham chiếu. Nó không phải là đối tượng được tham chiếu bởi một biến. Đó là một sự khác biệt rất lớn.

Trong ví dụ của bạn, nội dung của biến số list được chuyển làm giá trị cho phương thức removeElement.Giá trị này là tài liệu tham khảo cho đối tượng danh sách.

Điều đó có nghĩa là phương pháp removeElement hiện có quyền truy cập vào đối tượng danh sách đó (theo tham chiếu của nó) và có thể thao tác nó, ví dụ loại bỏ một phần tử. Nhưng nó không có quyền truy cập vào nội dung của biến mà phương thức được gọi. Vì vậy, nó không thể thay đổi nội dung của biến số list bên trong phương thức main (có thể với "pass-by-reference").

+0

Nó chỉ ra rằng ** trong java ** pass-by-value giống như pass-by-reference chỉ vì một 'value' có nghĩa là (trong java) một' tham chiếu'. (ngoại trừ các kiểu nguyên thủy) –

+1

Không, nó không giống nhau, vì không may từ "tham chiếu" có nghĩa là một điều khác trong cả hai ngữ cảnh. – Seelenvirtuose

5

Java luôn chuyển giá trị. Giá trị của bất kỳ biến số nào của loại Object thực sự là tham chiếu. Đó là lý do tại sao, ví dụ: == được cho là so sánh tham chiếu và bạn cần sử dụng .equals() để so sánh Object (s).

+1

Vì vậy, bạn đang nói - đối với các loại nguyên thủy, nó chuyển giá trị. Và đối với các kiểu tham chiếu, nó không truyền giá trị của đối tượng, thay vào đó nó chuyển tham chiếu của đối tượng. Nhưng nó chuyển tham chiếu này "theo giá trị". IMO đơn giản hơn nhiều đối với các kiểu nguyên thủy, giá trị được chuyển và đối với các loại tham chiếu, tham chiếu được chuyển. Tôi nghĩ rằng nhận xét của Gravity về [ObDuplicate] (http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) của câu hỏi này là tốt nhất - nó phụ thuộc vào những gì bạn có nghĩa là "tham khảo". –

+2

@ElliottFrisch Trong thực tế, nó không phải là giá trị của một _object_, nó là giá trị của _variable_. Và điều này rất có thể là nguyên nhân gây nhầm lẫn rất nhiều. – Seelenvirtuose

+0

Tôi không muốn tham gia cuộc tranh luận sôi nổi ở đây nhưng bạn có thể muốn đánh giá lại tuyên bố đó. Giá trị của một tham chiếu rõ ràng là một giá trị. Và các đối tượng được tham chiếu bằng tham chiếu. Nhưng giá trị của một đối tượng là một tham chiếu? Tôi muốn nói rằng giá trị của một đối tượng là tổng hợp của tất cả các trường của nó, nhưng tôi không nghĩ rằng có bất kỳ định nghĩa chính thức nào về điều đó. –

3

Trong trường hợp nguyên thủy, nó hoàn toàn là pass by value và trong trường hợp Objectspass by value of the reference.

Khi bạn vượt qua list từ phương pháp chính đến phương pháp removeElement() làm đối số có một tham chiếu (bản sao) khác được tạo trỏ đến cùng một thể hiện Danh sách. Bất kỳ thay đổi nào được thực hiện từ một trong hai tham chiếu sẽ phản ánh trên cùng một phiên bản thực tế. Tuy nhiên, nếu bạn chỉ định một tham chiếu cho một số đối tượng mới thì tham chiếu khác sẽ vẫn trỏ đến cùng một cá thể gốc.

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