To może być najgłupsze pytanie, jakie kiedykolwiek zadano, ale myślę, że jest to dość mylące dla początkującego Javy.
- Czy ktoś może wyjaśnić, co oznacza niezmienny ?
- Dlaczego jest
String
niezmienny? - Jakie są zalety / wady niezmiennych obiektów?
- Dlaczego zmienny obiekt, taki jak
StringBuilder
preferowany, zamiast String i vice-wers?
Dobry przykład (w Javie) zostanie naprawdę doceniony.
java
string
immutability
Ashokgelal
źródło
źródło
Odpowiedzi:
Niezmienny oznacza, że po zakończeniu wykonywania przez konstruktor obiektu nie można zmienić tego wystąpienia.
Jest to przydatne, ponieważ oznacza, że możesz przekazywać odniesienia do obiektu w pobliżu, nie martwiąc się, że ktoś inny zmieni jego zawartość. Zwłaszcza w przypadku współbieżności nie występują problemy z blokowaniem obiektów, które nigdy się nie zmieniają
na przykład
Foo
nie musi się martwić, że osoba dzwoniącagetValue()
może zmienić tekst w ciągu.Jeśli wyobrażasz sobie klasę podobną do członka
Foo
, ale z członkiem,StringBuilder
a nieString
członkiem, możesz zobaczyć, że osoba dzwoniącagetValue()
może zmienićStringBuilder
atrybutFoo
instancji.Uważaj również na różne rodzaje niezmienności, które możesz znaleźć: Eric Lippert napisał na ten temat artykuł na blogu . Zasadniczo możesz mieć obiekty, których interfejs jest niezmienny, ale za kulisami rzeczywisty zmienny stan prywatny (i dlatego nie może być bezpiecznie dzielony między wątkami).
źródło
Niezmienny obiekt to obiekt, w którym pola wewnętrzne (lub przynajmniej wszystkie pola wewnętrzne, które wpływają na jego zachowanie zewnętrzne) nie mogą zostać zmienione.
Niezmienne łańcuchy mają wiele zalet:
Wydajność: wykonaj następującą operację:
Podstawowy C dla metody substring () jest prawdopodobnie mniej więcej taki:
Pamiętaj, że nie trzeba kopiować żadnych znaków! Gdyby obiekt String był modyfikowalny (znaki mogłyby się później zmienić), musiałbyś skopiować wszystkie znaki, w przeciwnym razie zmiany znaków w podciągu zostaną odzwierciedlone w innym ciągu później.
Współbieżność: Jeśli wewnętrzna struktura niezmiennego obiektu jest poprawna, zawsze będzie poprawna. Nie ma szans, że różne wątki mogą stworzyć nieprawidłowy stan w tym obiekcie. Dlatego niezmienne obiekty są bezpieczne dla wątków .
Odśmiecanie: Śmieciarka znacznie łatwiej podejmuje logiczne decyzje dotyczące niezmiennych obiektów.
Istnieją jednak również wady niezmienności:
Wydajność: Zaczekaj, myślałem, że powiedziałeś, że wydajność jest zaletą niezmienności! Czasami tak jest, ale nie zawsze. Weź następujący kod:
Obie linie zastępują czwarty znak literą „a”. Drugi fragment kodu jest nie tylko bardziej czytelny, ale także szybszy. Zobacz, jak będziesz musiał wykonać podstawowy kod dla foo. Podciągi są łatwe, ale teraz, ponieważ w polu piątym jest już znak i coś innego może odnosić się do foo, nie możesz go po prostu zmienić; musisz skopiować cały ciąg znaków (oczywiście niektóre z tych funkcji są wyodrębnione do funkcji w prawdziwym bazowym C, ale chodzi tutaj o pokazanie kodu, który zostanie wykonany w jednym miejscu).
Zauważ, że konkatenat jest wywoływany dwukrotnie, co oznacza, że cały łańcuch musi być zapętlony! Porównaj to z kodem C
bar
operacji:Zmienna operacja na łańcuchach jest oczywiście znacznie szybsza.
Podsumowując: W większości przypadków potrzebujesz niezmiennego ciągu. Ale jeśli musisz dużo dodawać i wstawiać do łańcucha, potrzebujesz zmienności prędkości. Jeśli chcesz mieć korzyści z bezpieczeństwa współbieżności i odśmiecania, kluczem jest utrzymanie zmiennych obiektów w pobliżu metody:
Ponieważ
mutable
obiekt jest lokalnym odwołaniem, nie musisz się martwić o bezpieczeństwo współbieżności (tylko jeden wątek go dotyka). Ponieważ nigdzie indziej nie jest tam przywoływany, jest przydzielany tylko na stosie, więc jest on zwalniany natychmiast po zakończeniu wywołania funkcji (nie musisz się martwić o odśmiecanie). I zyskujesz wszystkie zalety wydajności, zarówno zmienności, jak i niezmienności.źródło
Passing pointers because Java is pass-by-reference
Czy Java nie jest „wartością przekazywaną?”W rzeczywistości String nie jest niezmienny, jeśli użyjesz sugerowanej powyżej definicji wikipedia.
Stan ciągu zmienia się po konstrukcji. Spójrz na metodę hashcode (). Łańcuch buforuje wartość hashcode w polu lokalnym, ale nie oblicza jej aż do pierwszego wywołania hashcode (). Ta leniwa ocena hashcode umieszcza String w interesującej pozycji jako niezmienny obiekt, którego stan zmienia się, ale nie można zaobserwować, że zmienił się bez użycia odbicia.
Może więc definicja niezmienności powinna być obiektem, którego zmiany nie można zaobserwować.
Jeśli stan zmienia się w obiekcie niezmiennym po jego utworzeniu, ale nikt go nie widzi (bez odbicia), czy obiekt nadal jest niezmienny?
źródło
Niezmienne obiekty to obiekty, których nie można zmienić programowo. Są szczególnie dobre w środowiskach wielowątkowych lub innych środowiskach, w których więcej niż jeden proces może zmieniać (mutować) wartości w obiekcie.
Jednak dla wyjaśnienia StringBuilder jest w rzeczywistości obiektem zmiennym, a nie niezmiennym. Zwykły ciąg java jest niezmienny (co oznacza, że po utworzeniu nie można zmienić leżącego pod nim łańcucha bez zmiany obiektu).
Załóżmy na przykład, że mam klasę o nazwie ColoredString, która ma wartość String i kolor String:
W tym przykładzie mówi się, że ColoredString jest zmienny, ponieważ można zmienić (mutować) jedną z jego kluczowych właściwości bez tworzenia nowej klasy ColoredString. Przyczyną tego może być na przykład założenie, że masz aplikację GUI, która ma wiele wątków i używasz aplikacji ColorfulStrings do drukowania danych w oknie. Jeśli masz instancję ColouredString, która została utworzona jako
Wtedy można oczekiwać, że ciąg będzie zawsze „niebieski”. Jeśli jednak inny wątek dostanie tę instancję i zadzwoni
Nagle, i prawdopodobnie nieoczekiwanie, miałbyś teraz „czerwony” sznur, kiedy chciałeś „niebieski”. Z tego powodu niezmienne obiekty są prawie zawsze preferowane przy przekazywaniu instancji obiektów dookoła. Kiedy masz przypadek, w którym zmienne obiekty są naprawdę konieczne, wtedy zwykle chronisz objet, przekazując tylko kopie z określonego pola kontroli.
Podsumowując, w Javie java.lang.String jest niezmiennym obiektem (nie można go zmienić po utworzeniu), a java.lang.StringBuilder jest obiektem zmiennym, ponieważ można go zmienić bez tworzenia nowej instancji.
źródło
Ciąg s1 = „Stary ciąg”;
Ciąg s2 = s1;
s1 = „Nowy ciąg”;
źródło
„niezmienny” oznacza, że nie można zmienić wartości. Jeśli masz instancję klasy String, każda wywoływana metoda, która wydaje się modyfikować wartość, faktycznie utworzy inny ciąg.
Aby zachować zmiany, powinieneś zrobić coś takiego: foo = foo.sustring (3);
Niezmienne kontra zmienne mogą być zabawne podczas pracy z kolekcjami. Zastanów się, co się stanie, jeśli użyjesz zmiennego obiektu jako klucza do mapy, a następnie zmienisz wartość (wskazówka: pomyśl o
equals
ihashCode
).źródło
java.time
Może być trochę za późno, ale aby zrozumieć, czym jest niezmienny obiekt, rozważ następujący przykład z nowego interfejsu API daty i godziny Java 8 ( java.time ). Jak zapewne wiesz, wszystkie obiekty daty z Java 8 są niezmienne, więc w poniższym przykładzie
Wynik:
Zostanie wydrukowany ten sam rok, co data początkowa, ponieważ
plusYears(2)
zwraca nowy obiekt, więc stara data pozostaje niezmieniona, ponieważ jest to obiekt niezmienny. Po utworzeniu nie można go dalej modyfikować, a zmienna daty nadal wskazuje na to.Tak więc ten przykład kodu powinien przechwycić i użyć nowego obiektu utworzonego i zwróconego przez to wywołanie
plusYears
.źródło
Naprawdę podoba mi się wyjaśnienie SCJP Sun Certified Programmer for Java 5 Study Guide .
źródło
Obiekty, które są niezmienne, nie mogą zmienić swojego stanu po ich utworzeniu.
Istnieją trzy główne powody używania niezmiennych obiektów, gdy tylko możesz, wszystkie z nich pomogą zmniejszyć liczbę błędów, które wprowadzasz w kodzie:
Istnieją również inne optymalizacje, które możesz wykonać w kodzie, gdy wiesz, że stan obiektu jest niezmienny - na przykład buforowanie obliczonego skrótu - ale są to optymalizacje i dlatego nie są tak interesujące.
źródło
Jedno znaczenie ma związek ze sposobem przechowywania wartości na komputerze. Na przykład ciąg .Net oznacza, że nie można zmienić ciągu w pamięci. Gdy myślisz, że go zmieniasz, w rzeczywistości tworzysz nowy łańcuch w pamięci i wskazujący istniejącą zmienną (która jest tylko wskaźnikiem do faktycznej kolekcji znaków gdzie indziej) na nowy ciąg.
źródło
s1="Hi"
: obiekts1
został utworzony z wartością „Cześć”.s2=s1
: obiekts2
jest tworzony w odniesieniu do obiektu s1.s1="Bye"
: wartość poprzedniegos1
obiektu nie zmienia się, ponieważs1
ma typ String, a typ String jest niezmiennym typem, zamiast tego kompilator tworzy nowy obiekt String z wartością „Bye” is1
odnosi się do niego. tutaj, gdy wypisujemys2
wartość, wynikiem będzie „Cześć”, a nie „Cześć”, ponieważs2
odnosi się do poprzedniegos1
obiektu, który miał wartość „Cześć”.źródło
Niezmienny oznacza, że po utworzeniu obiektu żaden z jego członków się nie zmieni.
String
jest niezmienny, ponieważ nie można zmienić jego zawartości. Na przykład:W powyższym kodzie ciąg s1 nie zmienił się,
s2
utworzono inny obiekt ( ) przy użycius1
.źródło
Niezmienne oznacza po prostu niezmienne lub niemodyfikowalne. Po utworzeniu obiektu łańcuchowego nie można zmienić jego danych ani stanu
Rozważ poniższy przykład,
Pomyślmy o poniższym schemacie,
Na tym schemacie widać nowy obiekt utworzony jako „Future World”. Ale nie zmieniaj „Przyszłości”.
Because String is immutable
.s
, nadal odnoszą się do „Przyszłości”. Jeśli chcesz zadzwonić do „Future World”,Dlaczego obiekty łańcuchowe są niezmienne w Javie?
źródło
Po utworzeniu nie można go zmienić. Rozważ klasę, której wystąpienie może być użyte jako klucz do tablicy mieszającej lub podobnej. Sprawdź najlepsze praktyki Java.
źródło
Niezmienne przedmioty
Obiekt uważa się za niezmienny, jeśli jego stan nie może się zmienić po jego zbudowaniu. Maksymalne poleganie na niezmiennych obiektach jest powszechnie akceptowane jako rozsądna strategia tworzenia prostego, niezawodnego kodu.
Niezmienne obiekty są szczególnie przydatne w aplikacjach współbieżnych. Ponieważ nie mogą zmienić stanu, nie mogą zostać uszkodzone przez interferencję nici ani zaobserwowane w niespójnym stanie.
Programiści często niechętnie stosują niezmienne obiekty, ponieważ martwią się kosztami stworzenia nowego obiektu, a nie jego aktualizacją. Wpływ tworzenia obiektów jest często przeceniany i można go zrównoważyć niektórymi korzyściami związanymi z niezmiennymi obiektami. Należą do nich zmniejszone obciążenie z powodu wyrzucania elementów bezużytecznych i eliminacja kodu potrzebnego do ochrony obiektów zmiennych przed uszkodzeniem.
Poniższe podrozdziały biorą klasę, której instancje są zmienne i wywodzą z niej klasę z instancjami niezmiennymi. W ten sposób podają ogólne zasady tego rodzaju konwersji i pokazują niektóre zalety niezmiennych obiektów.
Źródło
źródło
Ponieważ zaakceptowana odpowiedź nie odpowiada na wszystkie pytania. Jestem zmuszony udzielić odpowiedzi po 11 latach i 6 miesiącach.
Mam nadzieję, że miałeś na myśli nieruchomy obiekt (ponieważ moglibyśmy pomyśleć o niezmiennym odwołaniu ).
Obiekt jest niezmienny : po utworzeniu iff zawsze reprezentują tę samą wartość (nie ma żadnej metody zmieniającej wartość).
Przestrzegaj powyższej definicji, którą można sprawdzić, sprawdzając kod źródłowy Sting.java .
bezpieczniejsze od błędów.
łatwiejsze do zrozumienia.
i bardziej gotowi na zmiany.
Zawężenie pytania Dlaczego potrzebujemy zmiennego StringBuilder w programowaniu? Typowym zastosowaniem jest łączenie dużej liczby ciągów razem, jak poniżej:
Używając niezmiennych ciągów, tworzy się wiele tymczasowych kopii - pierwsza liczba ciągu („0”) jest faktycznie kopiowana n razy w trakcie budowania końcowego ciągu, druga liczba jest kopiowana n-1 razy, i tak na. Faktycznie kosztuje O (n2) czas na zrobienie całego tego kopiowania, nawet jeśli połączymy tylko n elementów.
StringBuilder został zaprojektowany w celu zminimalizowania tego kopiowania. Wykorzystuje prostą, ale sprytną wewnętrzną strukturę danych, aby w ogóle uniknąć kopiowania do samego końca, gdy poprosisz o końcowy ciąg znaków za pomocą wywołania toString ():
Uzyskanie dobrej wydajności jest jednym z powodów, dla których korzystamy ze zmiennych obiektów. Kolejnym jest wygodne udostępnianie: dwie części twojego programu mogą komunikować się wygodniej, dzieląc wspólną zmienną strukturę danych.
Więcej można znaleźć tutaj: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types
źródło
Niezmienny obiekt to taki, którego nie można zmodyfikować po jego utworzeniu. Typowym przykładem są literały łańcuchowe.
Język programowania AD, który staje się coraz bardziej popularny, ma pojęcie „niezmienność” poprzez słowo kluczowe „niezmiennik”. Sprawdź artykuł Dr.Dobb na ten temat - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Doskonale wyjaśnia problem.
źródło