Java nigdy nie jest przechodniem, prawda?... prawda? [duplikat]

Możliwy duplikat:
czy Java jest "pass-by-reference"?

Znalazłem dziś niezwykłą metodę Javy:

private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
     if (null == vsName)
       vsName = "";
     else
       vsName = vsName.trim();
     String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
     //SCR10638 - Prevent export of empty rows.
     if (shortenedVoiceSetName.length() > 0)
     {
       if (!voiceSetList.contains("#" + shortenedVoiceSetName))
         voiceSetList.add("#" + shortenedVoiceSetName);
     }
}

Według wszystkiego, co czytałem o zachowaniu Javy do przekazywania zmiennych, złożonych obiektów lub nie, ten kod nie powinien nic robić. Więc um...am coś mi umknęło? Czy jest jakaś subtelność, która została utracona na mnie, czy ten kod należy do thedailywtf?

Author: Community, 2009-04-28

6 answers

Jak powiedział Rytmis, Java przekazuje referencje przez wartość. Oznacza to, że możesz legalnie wywoływać metody mutujące na parametrach metody, ale nie możesz ich ponownie przypisać i oczekiwać propagacji wartości.

Przykład:

private void goodChangeDog(Dog dog) {
    dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
    dog = new StBernard(); // compiles, but has no effect outside the method
}

Edit: w tym przypadku oznacza to, że chociaż voiceSetList Może zmienić się w wyniku tej metody (może mieć do niej dodany nowy element), zmiany vsName nie będą widoczne poza metodą. Aby zapobiec zamieszanie, często zaznaczam moje parametry metody final, co zapobiega ich ponownemu przypisaniu (przypadkowo lub nie) wewnątrz metody. To uniemożliwiłoby kompilację drugiego przykładu.

 97
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 20:58:38

Java przekazuje referencje według wartości , więc otrzymujesz kopię referencji, ale obiekt odniesienia jest taki sam. Stąd ta metoda modyfikuje listę wejściową.

 27
Author: Rytmis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 20:32:25

Same referencje są przekazywane przez wartość.

[[0]] z języka Java jak programować, wydanie 4 by Deitel & Deitel: (str. 329)

W przeciwieństwie do innych języków, Java nie pozwala programiście wybrać, czy przekazać każdy argument według wartości lub odniesienia. Podstawowe zmienne typu danych są zawsze przekazywane według wartości. Obiekty nie są przekazywane do metod; raczej odniesienia do obiektów są przekazywane do metody. Same odniesienia są przekazywane przez wartość-kopię odniesienia przechodzi za metodę. Gdy metoda otrzymuje odniesienie do obiektu, metoda może manipulować obiekt bezpośrednio.

Używałem tej książki podczas nauki Javy na studiach. Świetne referencje.

Oto dobry artykuł wyjaśniający to. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

 3
Author: the_new_mr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-03 15:02:11

Cóż, może manipulować ArrayList - który jest obiektem... jeśli przekazujesz odwołanie do obiektu (nawet przekazywane przez wartość), zmiany w tym obiekcie zostaną odzwierciedlone do wywołującego. To jest pytanie?

 2
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 20:33:16

Myślę, że jesteś zdezorientowany, ponieważ vsname jest zmodyfikowany. Ale w tym kontekście jest to tylko zmienna lokalna, na tym samym poziomie co shortenedVoiceSetName.

 0
Author: PhiLho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 20:51:02

Nie jest dla mnie jasne, jakie jest dokładne pytanie w kodzie. Java jest pass-by-value, ale tablice są pass-by-reference, ponieważ nie przekazują żadnych obiektów, a tylko wskaźniki! Tablice składają się ze wskaźników, a nie rzeczywistych obiektów. To sprawia, że są bardzo szybkie, ale także niebezpieczne w obsłudze. Aby to rozwiązać, musisz je sklonować, aby uzyskać kopię, a nawet wtedy klonuje tylko pierwszy wymiar tablicy.

Po więcej szczegółów zobacz moją odpowiedź tutaj: w Javie, co to jest płytka Kopia? (Zobacz też inne moje odpowiedzi)

Nawiasem mówiąc, są pewne zalety, ponieważ tablice są tylko wskaźnikami: możesz (ab)używać ich jako zsynchronizowanych obiektów!

 -2
Author: mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-11 10:42:55