2012-06-13 12 views
16

Jestem nowicjuszem w Javie i mam kilka pytań na temat przydzielania obiektów. Na przykład,Przypisywanie obiektów Java

Test t1 = new Test(); 
Test t2 = t1; 
t1.i=1; 

Zakładając zmienna i jest zdefiniowana wewnątrz klasy Test mam prawo zakładać zarówno t1 i t2 punkt do tego samego obiektu, gdzie modyfikacja t1.i=1 wpływa zarówno t1 i t2? Właściwie to wypróbowałem to i wydaje mi się, że miałem rację. Jednak kiedy próbuję tego samego na String, modyfikacja odbywa się tylko z jednej strony, na której druga strona pozostaje nienaruszona. Jaki jest tego powód?

Edytuj: Sprawa, którą próbowałem z ciągiem.

String s1 = "0"; 
String s2 = s1;   
s1 = "1"; 
System.out.println(s1); 
System.out.println(s2); 

Zdaję sobie sprawę z mojego błędu, testując przypadki na ciąg, ponieważ jest niezmienny. Sytuacja, w której myślałem, że s1="1" modyfikuje ciąg znaków, zwraca referencję "1" do s1. Niemniej moje pytanie pozostaje. Czy Test t2 = t1; powoduje, że zarówno punkt t2, jak i t1 mają ten sam obiekt, lub że każdy z nich ma teraz swoje własne obiekty? Czy ta sytuacja dotyczy wszystkich obiektów w Javie?

+0

Co masz na myśli pod "wypróbuj to samo na String"? W obiekcie String nie ma żadnych metod modyfikacji samego ciągu. Przeczytaj uważnie dokumentację. – DRCB

+0

Jeśli opublikujesz kod testu, który robisz na String, możemy być bardziej szczegółowi, co robisz źle –

Odpowiedz

14

Masz rację, ale Struny to szczególny przypadek; są niezmienne i działają w tym przypadku jak prymitywy.

@newacct

cytuję http://docs.oracle.com/javase/tutorial/java/data/strings.html:

Uwaga: Klasa String jest niezmienna, tak, że gdy jest on tworzony obiekt String nie może być zmieniony. Klasa String ma numer metod, z których niektóre zostaną omówione poniżej, które wyglądają na modyfikuj ciągi. Ponieważ łańcuchy są niezmienne, do czego służą te metody, należy utworzyć i zwrócić nowy ciąg, który zawiera wynik operacji.

To właśnie sprawia, że ​​struny są specjalnym przypadkiem. Jeśli tego nie wiesz, możesz oczekiwać, że metody opisane w cytacie nie zwrócą nowych ciągów, co może prowadzić do nieoczekiwanych rezultatów.

@ user1238193

rozpatrywaniu następujące pytanie: „Czy t2 Test = t1; powodować zarówno T2 i punkt t1 do tego samego obiektu lub każdy ma teraz swoje własne obiekty Czy ta sytuacja dotyczy wszystkich obiektów w Javie? "

t1 i t2 wskazują ten sam obiekt. Dotyczy to dowolnego obiektu java (w tym niezmiennego)

+2

Nie ma" specjalnych przypadków ". Przypisanie do odniesienia dowolnego typu zmienia obiekt, na który wskazuje, bez wpływu na obiekt, na którym wskazywał. – newacct

+0

Struny są przypadkiem specjalnym; są obiektami, ale są niezmienne, co oznacza, że ​​jeśli spróbujesz je zmienić, na przykład String.replace, otrzymasz nowy obiekt zamiast tego samego obiektu zmutowanego. – Tom

+2

Nie, 'String' po prostu nie ma żadnej metody, która go zmienia. "spróbuj je zmienić" nie ma sensu; nie możesz "spróbować" zrobić czegoś, co nie istnieje. 'String.replace' daje ci nowy obiekt - o co ci chodzi? Tak mówi jego dokumentacja. 'Integer' i wiele innych klas jest niezmiennych. Możesz banalnie napisać klasę, która jest niezmienna, czyniąc pola prywatnymi i nie udostępniając żadnych metod zmiany jej pól. W każdym razie, zmienność jest nieistotna dla pytania, które pierwotnie dotyczyło zmiany pola na 'Test', ale nie ma żadnych publicznych pól na' String'u – newacct

3

Masz całkowitą rację, ponieważ zarówno t1 jak i t2 odnoszące się do tego samego obiektu, dowolna zmiana stanu obiektu wpłynie na oba.

String jest obiektem niezmiennym. Więc nie można go w ogóle zmodyfikować. see this, aby uzyskać więcej informacji o niezmiennym obiekcie w java.

+0

http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html –

+0

To nie wyjaśnia problemu. To samo dotyczy "Testu": 'Test s1 = new Test (2); Test s2 = s1; s1 = nowy test (1); ' – newacct

2

String objects are immutable.


EDIT

Czy Test t2 = t1; przyczyną zarówno t2 i punkt t1 do tego samego przedmiotu lub każdy ma teraz swoje własne obiekty?

Tak. Chociaż t2 jest nowym odnośnikiem, ale wskaże ten sam obiekt, ponieważ kazałeś mu to zrobić. Utwórz nowe odniesienie t2 typu Test i pozwól mu wskazywać ten sam obiekt, na który wskazuje t1.

Ale jeśli zrobisz to z String s, a następnie zrobisz coś takiego jak s1 = "1" ;, robisz s1 punkt do innego obiektu String. Możesz myśleć o tym w kategoriach s1 = new String(1);.

+0

To nie wyjaśnia problemu. To samo dotyczy "Testu": 'Test s1 = new Test (2); Test s2 = s1; s1 = nowy test (1); ' – newacct

+0

@newacct OP edytował post później. Pierwszy wpis odpowiadał tylko za pomocą tych kilku słów. Będę edytować mój post teraz. Dzięki za wskazanie. –

+0

Nawet przed edycją "Ciąg jest niezmienny" nie jest poprawną odpowiedzią. Powiedział "kiedy próbowałem tego samego na String"; Odpowiedź brzmi: "To, co powiedziałeś, jest niemożliwe, nie da się zrobić tego samego z String" – newacct

1

Łańcuch to obiekt jak każdy inny. Każda przypisana zmienna odnosi się do tej samej instancji obiektu, tak jak robisz z obiektem testowym.

Należy jednak pamiętać, że String nie ma pola, które można ustawić tak jak w przypadku testu, więc zasadniczo nie można wykonać tego samego testu, więc nie ma możliwości przeniesienia kodu z obiektu testowego na obiekt typu String.

uzyskać odwrotne zachowanie używając prymitywnych typów, takie długi, int itp są one przypisane do zmiennych „wartością”, więc jeśli nie

int t1 = 12; 
int t2 = t1; 
t1=15; 

t2 wciąż ma wartość 12

5

Ty masz rację z pierwszym założeniem. Z następującą linię kodu:

Test t1 = new Test(); 

utworzyć nowy obiekt testowy, aw tym samym czasie utworzyć wzorcowe wykorzystywane do badania o nazwie t1 odnieść się do niego.

Na drugiej linii kodu, który pisał:

Test t2 = t1; 

w rzeczywistości stworzenie innego odniesienia testową i przypisać go do odnoszą się do tego samego obiektu, który odnosi się do t1.

Tak więc t1.i = 1; wpłynie na t2.i, ponieważ w końcu jest to ten sam obiekt.

Jeśli chodzi o napisy, ciągi znaków są niezmienne i nie można ich modyfikować po utworzeniu instancji.

Odnośnie swojej EDIT:

String s1 = "0"; 
String s2 = s1;   
s1 = "1"; 
System.out.println(s1); 
System.out.println(s2); 

Będą drukować różne wyniki, ponieważ kiedy rzeczywiście powiedzieć

s1 = "1"; 

jesteś rzeczywiście wiążącej S1 do innego obiektu String, ale s2 nadal będzie refering obiekt o wartości "0".

2

W obu przypadkach robisz zupełnie inne rzeczy. W pierwszym przypadku z t1.i = 1; modyfikujesz obiekt wskazany przez t1.W drugim przypadku, z t1 = "1";, zmieniasz odniesienie do punktu do innego obiektu (podobny do tego, kiedy zrobiłeś t2 = t1;.

Jeśli zrobisz to samo Test, które miało miejsce w drugim przypadku można uzyskać Taki sam wynik (zakładając Test ma konstruktora, który bierze całkowitą).

Test t1 = new Test(5); 
Test t2 = t1;   
t2 = new Test(1); // Here we are assigning to the variable, just like your 2nd example 
System.out.println(t1); 
System.out.println(t2); 

Ludzie wspomnieć, że String jest niezmienna Ale to nie ma znaczenia i nie ma pojęcia „zmienności” w języku i nie ma żadnej różnicy pomiędzy jak działają klasy "zmienne" i "niezmienne". Nieformalnie mówimy, że klasa jest "niezmienna", jeśli nie ma w niej miejsca ds można ustawić lub dowolne metody, które mogą zmienić jego wewnętrzną zawartość. Tak jest w przypadku String. Ale zmienna klasa działałaby dokładnie tak samo, jeśli po prostu nie zrobisz nic, by ją zmutować.

+0

Przed anulowaniem i skomentowaniem innych odpowiedzi uprzejmie prosimy o sprawdzenie historii edycji pytania. To da ci wskazówkę, dlaczego wiele odpowiedzi, mówiąc to samo, zostało przegłosowanych. –