2013-02-16 17 views
6

Witam Im studiuje dla mojego egzaminu scja i mam pytanie o przekazywanie ciągu przez wartość/wartość i jak są one niezmienne. Poniższy kod wyświetla "abc abcfg".Java String niezmienny przekazywany przez referencję/wartość

Co chcę wiedzieć, dlaczego tak się dzieje? Nie rozumiem, co dzieje się w środku metody f. Łańcuch jest przekazywany według wartości, więc na pewno powinien zmienić się na "abcde" w metodzie? Bo jeśli b + = "fg" dołącza do łańcucha, dlaczego nie działa w metodzie?

Dzięki!

public class Test { 

    public static void main(String[] args){ 
     String a =new String("abc"); 
     String b = a; 
     f(b); 
     b+="fg" 
     System.out.println(a + " " + b); 
    } 

    public static void f(String b){ 
     b+="de"; 
     b=null; 
    } 
} 
+1

Kluczową sprawą do zapamiętania jest to, że referencje są przekazywane wartością. f otrzymuje kopię odwołania, które początkowo jest wskaźnikiem do "fg". –

Odpowiedz

2

W swojej metodzie f() jesteś przypisując nowy ciąg do parametru b, ale parametry są jak zmienne lokalne, więc przypisywania coś do nich nie ma wpływu na cokolwiek poza metody. Dlatego ciąg znaków, który przekazałeś, pozostaje niezmieniony po wywołaniu metody.

+0

, więc musiałbym zrobić b = f (b) i zwrócić ciąg z metody f? –

+0

Dokładnie! Nawet wtedy, dopóki nie zwrócisz łańcucha, nie będzie żadnego efektu poza metodą. – Bohemian

+0

Wskazuje również, że jeśli wykonujesz b = f (b) i zwrócisz String z aktualnym kodem, pozostanie ci wynik "abc nullfg", jak mówisz b = null. –

0

Po przekazaniu łańcucha znaków do metody tworzy on nowy obiekt String w metodzie. Jeśli umieścisz instrukcję println w swojej metodzie, to:

public static void f(String b){ 
    b+="de"; 
    System.out.println(b); 
    b=null; 
} 

Zobaczysz wyjście "abcde".

Jednak po wyjściu z metody wracasz do oryginalnego obiektu , który nie został zmieniony. Dlatego dodanie do niego polecenia fg spowoduje wygenerowanie tylko NOWEGO ciągu znaków (b) zawierającego "abcfg".

8

Linia b+="de"; w funkcjach void f(String b) tworzy zupełnie nowy obiekt o numerze String, który nie wpływa na obiekt w funkcji main.

Więc kiedy mówimy String jest niezmienne gdy średnia dowolny zmiana na String obiektu spowoduje stworzenie całkowicie nowej String obiekt

public class Test { 
    public static void main(String[] args){ 
     String a =new String("abc"); 

     String b = a; // both a & b points to the same memory address 

     f(b); // has no effect 

     // b still has the value of "abc" 
     b+="fg" // a new String object that points to different location than "a" 

     System.out.println(a + " " + b); // should print "abc abcfg" 
    } 

public static void f(String b){ 
    b+="de"; // creates a new object that does not affect "b" variable in main 
    b=null; 
} 
} 
3

ta linia kodu:

b += "de"; 

W przybliżeniu oznacza:

b = b + "de"; 

Która tworzy nowy Ciąg i zapisuje go w lokalnej zmiennej "b". Odniesienie poza metodą nie jest w żaden sposób zmienione przez to. Jest kilka kluczowych rzeczy do zapamiętania, kiedy próbujesz zrozumieć, jak/dlaczego to działa w ten sposób.

  1. W języku Java wszystkie argumenty metody są przekazywane według wartości.
  2. Metody mają stos lokalny, w którym przechowywane są wszystkie ich dane, łącznie z argumentami metody.

Po przypisaniu nowego obiektu do zmiennej, która została przekazana do metody, zastępujesz tylko adres w lokalnym stosie, z adresem utworzonego nowego obiektu. Rzeczywisty adres obiektu poza metodą pozostaje taki sam.

0

Twój tworząc nowy obiekt String, kiedy mówisz coś b + = "de"

To jak powiedzenie b = new String (b + "de");

Jeśli naprawdę chcesz zachować wartości przekazanej w następnie użyć StringBuilder takiego:

StringBuilder a =new StringBuilder("abc"); 
     StringBuilder b = a; 
     f(b); 
     b.append("fg"); 
     System.out.println(a + " " + b); 
    } 

    public static void f(StringBuilder b){ 
     b.append("de"); 
     b=null; 
    } 

Teraz twoje wyjście będzie „abcdefg”, ponieważ obiekt StringBuilder b został przekazany do f jako wartość przedmiotu samo. Zmodyfikowałem wartość bez użycia "new", aby wskazać inny obiekt. Mam nadzieję, że teraz jest jasne.