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:
Object o = "Hello";
mutate(o)
System.out.println(o);
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
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:
AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!
private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
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.
To wszystko jest na tym obrazku:
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ę:
public class Ref<T> {
private T value;
public Ref(T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T anotherValue) {
value = anotherValue;
}
@Override
public String toString() {
return value.toString();
}
@Override
public boolean equals(Object obj) {
return value.equals(obj);
}
@Override
public int hashCode() {
return value.hashCode();
}
}
przypadek testowy:
public void changeRef(Ref<String> ref) {
ref.set("bbb");
}
// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
AtomicReference
(dla nieprymitywów)? Lub AtomicSomething
(np . AtomicBoolean
:) dla prymitywów?
int
zamiast Integer
, bool
zamiast Boolean
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”:
„... W Javie istnieje dokładnie jeden tryb przekazywania parametrów - przekazywanie przez wartość - dzięki czemu wszystko jest proste. ..”
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.
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.