Java jest myląca, ponieważ wszystko jest przekazywane według wartości . Jednak w przypadku parametru typu referencyjnego (tj. Nie jest to parametr typu pierwotnego) jest to samo odniesienie, które jest przekazywane przez wartość, stąd wydaje się, że jest to element przekazujący (a ludzie często twierdzą, że tak jest). Tak nie jest, jak pokazano poniżej:
Object o ="Hello";
mutate(o)System.out.println(o);privatevoid mutate(Object o){ o ="Goodbye";}//NOT THE SAME o!
Wydrukuje Hellona konsoli. Opcje, jeśli chcesz, aby powyższy kod został wydrukowany, Goodbyeto użycie jawnego odniesienia w następujący sposób:
Ponadto tablica o długości 1 może być użyta do utworzenia odniesienia, jeśli naprawdę chcesz zmylić ludzi :)
Christoffer
2
AtomicReference i odpowiadające im klasy (AtomicInteger) są najlepsze do takich operacji
Naveen
3
AtomicReference to przesada, niekoniecznie chcesz mieć tam barierę pamięci, a może cię to kosztować. JRuby miał problem z wydajnością z powodu niestabilnej zmiennej używanej podczas konstruowania obiektu. Opcja używania tablicy jako odniesienia ad-hoc wydaje mi się wystarczająco dobra i widziałem, że była używana więcej niż raz.
Elazar Leibovich
Nie sądzę, żeby to było mylące, jednak jest to normalne zachowanie. Typy wartości istnieją na stosie, a typy referencyjne na stercie, ale odniesienia do typów referencyjnych również istnieją na stosie. W ten sposób zawsze operujesz wartością znajdującą się na stosie. Uważam, że pytanie brzmiało: czy można przekazać referencję ze stosu, która wskazuje na inną wartość, która również znajduje się na stosie. Albo podać odniesienie do innego odniesienia, które wskazuje na jakąś wartość, która żyje na kupie?
eomeroff
to mam świetne informacje. Używałem tablic, ale wygląda na to, że jest to coś stworzonego do tego zadania. nie wiem jak to
wygląda w
65
Czy mogę przekazywać parametry przez odniesienie w Javie?
Nie.
Czemu ? Java ma tylko jeden sposób przekazywania argumentów do metod: według wartości.
Uwaga:
W przypadku prymitywów jest to łatwe do zrozumienia: otrzymujesz kopię wartości.
W przypadku wszystkich innych otrzymujesz kopię referencji i nazywa się to również przekazywaniem wartości.
Dlaczego nie użyć zamiast tego java.lang.ref.Reference?
Kodowane na stałe
java.lang.ref.Reference nie ma ustawionej metody, nie można jej zmieniać
dfa
dlaczego nie użyć AtomicReference(dla nieprymitywów)? Lub AtomicSomething(np . AtomicBoolean:) dla prymitywów?
Arvin
Niestety <T> nie akceptuje typów pierwotnych. Czy chcesz to zrobić: Ref <int>
jk7
1
@ jk7 Czy naprawdę ważne jest, aby używać intzamiast Integer, boolzamiast Booleani tak dalej? Oznacza to, że klasy opakowania (które są automatycznie rozpakowywane, jeśli martwisz się o składnię) nie działają?
Paul Stelian
18
Od Jamesa Goslinga w „The Java Programming Language”:
„... W Javie istnieje dokładnie jeden tryb przekazywania parametrów - przekazywanie przez wartość - dzięki czemu wszystko jest proste. ..”
@ingyhere:: The pronouncement of the language god should be declared the answerNiezupełnie. Wbrew temu, co myśli lub wierzy twórca Javy, absolutną odpowiedzią byłby cytat ze specyfikacji języka.
paercebal
1
W rzeczywistości jest w JLS, w sekcji 8.4.1 , a JLS cytuje Goslinga jako pierwszego autora: „Kiedy wywoływana jest metoda lub konstruktor (§15.12), wartości rzeczywistych wyrażeń argumentów inicjują nowo utworzone zmienne parametrów , każda zadeklarowanego typu, przed wykonaniem treści metody lub konstruktora. "
ingyhere
Dokładnie. Sarkazm od członków o niskiej reputacji nie jest pomocny.
duffymo
11
Myślę, że nie możesz. Najlepszą opcją może być hermetyzacja rzeczy, którą chcesz przekazać „przez ref”, do innej instancji klasy i przekazanie (zewnętrznej) referencji klasy (według wartości). Jeśli widzisz co mam na myśli...
tzn. Twoja metoda zmienia stan wewnętrzny przekazywanego obiektu, który jest następnie widoczny dla wywołującego.
Inną opcją jest użycie tablicy, np.
void method(SomeClass[] v) { v[0] = ...; }
Ale 1) tablica musi być zainicjalizowana przed wywołaniem metody, 2) nadal nie można w ten sposób zaimplementować np. Metody swap ... Tak jest w JDK, np java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]). W.
Odpowiedzi:
Java jest myląca, ponieważ wszystko jest przekazywane według wartości . Jednak w przypadku parametru typu referencyjnego (tj. Nie jest to parametr typu pierwotnego) jest to samo odniesienie, które jest przekazywane przez wartość, stąd wydaje się, że jest to element przekazujący (a ludzie często twierdzą, że tak jest). Tak nie jest, jak pokazano poniżej:
Wydrukuje
Hello
na konsoli. Opcje, jeśli chcesz, aby powyższy kod został wydrukowany,Goodbye
to użycie jawnego odniesienia w następujący sposób:źródło
Nie.
Czemu ? Java ma tylko jeden sposób przekazywania argumentów do metod: według wartości.
Uwaga:
W przypadku prymitywów jest to łatwe do zrozumienia: otrzymujesz kopię wartości.
W przypadku wszystkich innych otrzymujesz kopię referencji i nazywa się to również przekazywaniem wartości.
To wszystko jest na tym obrazku:
źródło
W Javie nie ma nic na poziomie językowym podobnym do ref . W Javie istnieje tylko przekazywanie wartości semantycznej
Z ciekawości możesz zaimplementować semantykę podobną do ref w Javie, po prostu opakowując swoje obiekty w zmienną klasę:
przypadek testowy:
źródło
AtomicReference
(dla nieprymitywów)? LubAtomicSomething
(np .AtomicBoolean
:) dla prymitywów?int
zamiastInteger
,bool
zamiastBoolean
i tak dalej? Oznacza to, że klasy opakowania (które są automatycznie rozpakowywane, jeśli martwisz się o składnię) nie działają?Od Jamesa Goslinga w „The Java Programming Language”:
źródło
The pronouncement of the language god should be declared the answer
Niezupełnie. Wbrew temu, co myśli lub wierzy twórca Javy, absolutną odpowiedzią byłby cytat ze specyfikacji języka.Myślę, że nie możesz. Najlepszą opcją może być hermetyzacja rzeczy, którą chcesz przekazać „przez ref”, do innej instancji klasy i przekazanie (zewnętrznej) referencji klasy (według wartości). Jeśli widzisz co mam na myśli...
tzn. Twoja metoda zmienia stan wewnętrzny przekazywanego obiektu, który jest następnie widoczny dla wywołującego.
źródło
Java jest zawsze przekazywana przez wartość.
Kiedy przekazujesz prymityw, jest to kopia wartości, kiedy przekazujesz obiekt, jest to kopia wskaźnika referencyjnego.
źródło
Inną opcją jest użycie tablicy, np.
void method(SomeClass[] v) { v[0] = ...; }
Ale 1) tablica musi być zainicjalizowana przed wywołaniem metody, 2) nadal nie można w ten sposób zaimplementować np. Metody swap ... Tak jest w JDK, npjava.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])
. W.źródło