2012-07-20 12 views
5

Wiem, że w Javie wszystko jest przekazywane przez wartość. Ale dla obiektów jest to wartość odniesienia do obiektu, który jest przekazywany. Oznacza to, że czasami obiekt można zmienić za pomocą parametru, dlatego, jak sądzę, ludzie mówią: Nigdy nie modyfikuj parametrów.Przejść według "wartości referencyjnej"? Potrzebne pewne wyjaśnienie

Ale w poniższym kodzie dzieje się coś innego. s w changeIt() nie zmienia się, kiedy wrócisz do main():

public class TestClass { 

    static String str = "Hello World"; 

    public static void changeIt(String s) { 
     s = "Good bye world"; 
    } 

    public static void main(String[] args) { 
     changeIt(str); 
     System.out.println(str); 
    } 
} 

Zgaduję - i chciałbym potwierdzenie - że kiedy mówisz s = "something" to ten sam lub równoważny mówiąc String s = new String("something"). Czy to dlatego nie zmienia się s? Czy jest lokalnie przydzielony zupełnie nowy obiekt, który zostaje odrzucony po wyjściu z changeIt()?

+1

Widziałem już tego rodzaju pytania/odpowiedzi, a ja * nadal * mam wrażenie, że potrzebuję recenzji. +1 – BlackVegetable

+0

Nie zmienia się, ponieważ łańcuchy znaków w języku Java są obiektami niezmiennymi. – anio

+1

@anio Nie, to nie jest powód, dla którego ten konkretny kod nie zmienia łańcucha. Byłoby to takie samo zachowanie dla dowolnego obiektu, niezmienne lub nie (ponieważ wykonuje przypisanie, nie wywołuje żadnej metody na otrzymanym obiekcie). – nos

Odpowiedz

4

że kiedy mówisz s = "coś" jest taki sam lub równoważny mówiąc łańcuch s = new String ("coś")

Tak, bardzo dużo. (chociaż JVM może robić optymalizacje, tak że ten sam literał ciągu użyty kilka razy odnosi się do tego samego obiektu String).

Czy to dlatego nie ulega zmianie? Czy jest przypisany lokalnie nowy obiekt, który zostaje wyrzucony po zakończeniu zmiany()

Tak. Jak już mówisz, wszystko jest przekazywane przez wartość Java, nawet odniesienia do obiektu. Zatem zmienna s w changeIt(String s) jest inna od wartości str, której używasz w main(), jest to po prostu lokalna zmienna w metodzie changeIt. Ustawienie odniesienia do innego obiektu nie wpływa na rozmówcę z changeIt.

Zauważ, że obiekt String s znajdują się wciąż ten sam ciąg jako str odnosi się przy wejściu do metody changeIt() przed przypisać inny obiekt do s

Jest jeszcze jedna rzecz, którą musisz mieć świadomość, i że jest to, że Strings są niezmienne. Oznacza to, że żadna metoda wywoływana w obiekcie typu string nie zmieni tego ciągu. na przykład wywoływanie s.toLowerCase() w ramach metody changeIt() również nie wpłynie na dzwoniącego. To dlatego, że String.toLowerCase() nie zmienia obiektu, ale raczej zwraca nowy obiekt String.

0

Tak, teraz "S" wskazuje na zupełnie nowy obiekt, którego zakres jest ograniczony do tej metody. String może nie być doskonałym przykładem do zrozumienia koncepcji pass-by-value. Zamiast łańcucha, powiedzmy, przekazać pewne zmienne odwołania do obiektu i wprowadzić zmiany w tym, które przydzielają nowy obiekt wewnątrz metody. Nie widzisz ich poza obiektem.

public class MyMain { 

    private static void testMyMethod(MyMain mtest) { 
     mtest=new MyMain(); 
     mtest.x=50; 
     System.out.println("Intest method"+mtest.x); 
    } 
    int x=10; 
    public static void main(String... args) 
    { 
     MyMain mtest = new MyMain(); 
     testMyMethod(mtest); 
     System.out.println("In main method: "+mtest.x); 
    } 
} 

Przeczytaj drugie odpowiedzi w tym SO discussion.

+0

To jest złe, widzisz zmiany dokonane w zmiennym obiekcie: 'static Point myPoint = new Point (0,0); public static void changeIt (Point p) { p.setLocation (1,0); } \t public static void main (String [] args) { changeIt (myPoint); System.out.println (myPoint); \t} 'Wypisze' java.awt.Point [x = 1, y = 0] ' – NominSim

+0

@NominSim: Sprawdź mój przykład, a kiedy parametr jest ostateczny, nie można przypisać nowego obiektu do to odniesienie. – kosa

+0

@NominSim: I jeśli to możliwe, drugą odpowiedź w tym linku. http://stackoverflow.com/questions/40480/is-java-pass-by-reference – kosa

3

Kiedy piszesz

s = "Good bye world"; 

zmieniasz wartość s być odniesienie do nowego łańcucha. Nie zmieniasz wartości łańcucha, do którego odwołuje się s.

Powiązane problemy