2015-04-19 15 views
9

Istnieje wiele dyskusji w stackoverflow dotyczących przekazywania wartości i przekazywania przez odniesienie. Ale chcę wiedzieć, co dzieje się w następującym scenariuszu? Ta strona mówi, że java jest przekazywana według wartości. Is Java "pass-by-reference" or "pass-by-value"?.Jawne przekazywanie list metodom działającym jak przekazywanie przez odniesienie

W przypadku następującego kodu, element jest usuwany z metody removeElement, usuwa piątego elementu z listy po wydrukowaniu listy.

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 
     } 
} 

Dane wyjściowe programu to [1, 1, 2, 3, 5, 13, 21].

Czy ktoś może wyjaśnić, jak to jest przekazywać wartość, a nie przekazywać przez odniesienie?

+1

To niemożliwe, to nie jest dupe. –

+7

Faktycznie, stwierdzenie, że Java jest "wartością przekazywaną", jest niepotrzebnie mylące i wymaga skręcania normalnego znaczenia słów angielskich. Java ma dwa typy wartości: typy podstawowe i typy odniesienia (obiekty i tablice). W przypadku typów pierwotnych wartość jest przekazywana. W przypadku typów odniesienia odniesienie jest przekazywane. Niektórzy ludzie lubią dodawać, że ten odnośnik jest przekazywany "według wartości", ale to nic nie dodaje nikomu do zrozumienia tematu. Ponieważ referencja jest przekazywana dla typów odniesienia, zobaczysz modyfikacje, które wprowadziłeś do obiektu w wywołującym metodę. –

Odpowiedz

1

Mimo że to pytanie zadaje (ponownie) pytanie o różnicę między "wartością przekazywaną" i "różnicą", myślę, że istnieje błędne przekonanie, które powoduje tyle zamieszania. To musi zostać rozwiązane:

W rzeczywistości wywołanie metody przekazuje wszystkie parametry według wartości. Jak Erwin Bolwidt wskazał w swoich komentarzach, istnieją dwa rodzaje typów:

  • prymitywne typy
  • typy referencyjne

JLS (§4) stwierdza go:

języka programowania Java jest statycznie napisanym językiem, co oznacza, że ​​każda zmienna i każde wyrażenie ma typ znany w czasie kompilacji.
[...]
Istnieją dwa rodzaje typów w języku programowania Java: typy podstawowe (§4.2) i typy odniesienia (§4.3).

Mówiąc o "wartości przekażnika", oznacza to, że zawartość zmiennej jest przekazywana przez wartość, gdy jest używana jako parametr dla wywołania metody. A treść referencyjnej zmiennej pisanej jest odniesieniem. Nie jest to obiekt, do którego odnosi się zmienna. To ogromna różnica.

W powyższym przykładzie treść zmiennej list jest przekazywana jako wartość do metody removeElement.Ta wartość jest odniesieniem do obiektu listy.

To ponadto oznacza, że ​​metoda removeElement ma teraz dostęp do tego obiektu listy (przez swój odnośnik) i może nim manipulować, na przykład usunąć element. Ale nie ma dostępu do zawartości zmiennej, z którą wywołano tę metodę. Nie można więc zmienić zawartości zmiennej list w metodzie main (co byłoby możliwe przy "przekazywaniu przez odniesienie").

+0

Okazuje się, że ** w java ** pass-by-value jest tym samym co pass-by-reference tylko dlatego, że 'wartość' oznacza (w java) a' reference'. (z wyjątkiem typów pierwotnych) –

+1

Nie, to nie to samo, ponieważ niestety słowo "odwołanie" oznacza inną rzecz w obu kontekstach. – Seelenvirtuose

5

Java jest zawsze przekazywana według wartości. Wartość dowolnej zmiennej typu Object jest w rzeczywistości odniesieniem. Dlatego, na przykład, == jest podobno porównaniem porównawczym i musisz użyć .equals() do porównania Object (s).

+1

Więc mówisz - dla typów pierwotnych przekazuje wartość. W przypadku typów odniesienia nie przekazuje wartości obiektu, lecz przekazuje referencję obiektu. Ale przekazuje to odniesienie "według wartości". O wiele łatwiej jest powiedzieć IMO, że dla typów pierwotnych wartość jest przekazywana, a dla typów referencyjnych - referencja. Myślę, że komentarz Gravity na temat [ObDuplicate] (http://stackoverflow.com/questions/40480/is-java-pass-by-reference- or-pass-by-value) tego pytania jest najlepszy - to zależy od tego, co masz na myśli "odniesienie". –

+2

@ElliottFrisch W rzeczywistości nie jest wartością _object_, jest wartością _variable_. I to jest najprawdopodobniej przyczyną tak wielkiego zamieszania. – Seelenvirtuose

+0

Nie chcę wdawać się w gorącą debatę tutaj, ale możesz chcieć dokonać ponownej oceny tego stwierdzenia. Wartość odniesienia jest wyraźnie wartością. A obiekty są przywoływane przez odniesienie. Ale wartość obiektu jest odniesieniem? Powiedziałbym, że wartość obiektu jest sumą wszystkich jego pól, ale nie sądzę, że istnieje jakakolwiek oficjalna definicja tego. –

3

W przypadku prymitywów to czysto pass by value, aw przypadku Objects jest to pass by value of the reference.

Po przekazaniu list z metody głównej do metody removeElement() jako argumentu, tworzona jest kolejna (kopia) referencja, która wskazuje tę samą instancję listy. Wszelkie zmiany dokonane z jednego z odnośników będą dotyczyć tej samej rzeczywistej instancji. Jednak jeśli przypiszesz jeden z odniesień do jakiegoś nowego obiektu, inne odniesienia będą nadal wskazywać na to samo oryginalne wystąpienie.

Powiązane problemy