Değişmez ile ne kastedilmektedir?


400

Bu şimdiye kadar sorulan en aptalca soru olabilir ama bir Java acemi için oldukça kafa karıştırıcı olduğunu düşünüyorum.

  1. Birisi değişmez ile ne kastedildiğini açıklığa kavuşturabilir mi?
  2. Neden Stringdeğişmez?
  3. Değişmez cisimlerin avantajları / dezavantajları nelerdir?
  4. StringBuilderDize ve tersi gibi bir değişken nesne neden tercih edilmeli?

Güzel bir örnek (Java'da) gerçekten takdir edilecektir.


73
Bakın, bu kadar aptalca bir soru değildi. Sorduğun için sevindim!
DOK

2
Bu arada, bunun en aptalca soru olduğunu sanmıyorum :) Bence anlaması oldukça önemli bir kavram
Jason Coco

1
StringBuilder dediğinde, mutable sınıfı StringBuffer demek istemedin mi? String ve StringBuffer işlevlerinde String ve StringBuilder'den daha benzerdir. StringBuffer etkili bir şekilde değiştirilebilir bir dizedir.
Derek Mahar

3
Java için yeni programcıların diğer giriş soruları için bir aramada bulabilmeleri için bu soruyu "acemi" etiketini eklememizi önerebilir miyim?
Derek Mahar

Yanıtlar:


268

Değişmez, bir nesne için yapıcı yürütmeyi tamamladığında bu örneğin değiştirilemeyeceği anlamına gelir.

Bu, başka birinin içeriğini değiştireceğinden endişe etmeden etrafındaki nesneye referanslar iletebileceğiniz anlamına gelir. Özellikle eşzamanlılık ile uğraşırken, asla değişmeyen nesnelerle kilitleme sorunu yoktur

Örneğin

class Foo
{
     private final String myvar;

     public Foo(final String initialValue)
     {
         this.myvar = initialValue;
     }

     public String getValue()
     {
         return this.myvar;
     }
}

Fooarayanın getValue()dizedeki metni değiştirebileceğinden endişelenmesine gerek yoktur .

Eğer benzer bir sınıf hayal ederse Fooancak birlikte, StringBuilderyerine bir daha Stringbir üyesi olarak, bir arayan için olduğunu görebilirsiniz getValue()değiştirmek mümkün olacaktır StringBuilderbir vasfını Fooörneği.

Ayrıca bulabileceğiniz farklı değişmezlik türlerine dikkat edin: Eric Lippert bunun hakkında bir blog makalesi yazdı . Temelde arayüzü değiştirilemeyen, ancak sahne arkasında gerçek mutables özel durumu olan nesneler olabilir (ve bu nedenle evreler arasında güvenli bir şekilde paylaşılamaz).


3
En az bir kez değer atamak için bir arg yapıcı eklemeniz gerektiğini düşünüyorum. Mevcut kodun noktası net değil çünkü gerçekten değiştirilecek bir değer yok :).
Georgy Bolyuba

4
Alanı salt okunur yapmalısınız. Alanın değişmez olduğu tamamen açıktır. Şu anda Kongre tarafından değişmez
JaredPar

7
Üye myVar, bunun gerçekten değişmez olması için nihai olmalıdır.
laz

13
MyVar'a Foo dışında erişilemez. Ancak, finalin varlığı, ileride sınıfını değiştirebilecek herkese, değerinin değişmesi anlamına gelmediğini gösterir. Bu gibi durumlarda olabildiğince açık olmayı tercih ediyorum.
laz

2
"Referans türleri yalnızca son anahtar kelime kullanılarak değiştirilemez hale getirilemez. Final yalnızca yeniden atanmayı önler." dan en.wikipedia.org/wiki/Immutable_object
Yousha Aleayoub

81

Değişmez bir nesne, dahili alanların (veya en azından harici davranışını etkileyen tüm dahili alanların) değiştirilemediği bir nesnedir.

Değişken olmayan dizelerin birçok avantajı vardır:

Performans: Aşağıdaki işlemi gerçekleştirin:

String substring = fullstring.substring(x,y);

Substring () yöntemi için temeldeki C muhtemelen böyle bir şeydir:

// Assume string is stored like this:
struct String { char* characters; unsigned int length; };

// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
    struct String* out = malloc(sizeof(struct String));
    out->characters = in->characters + begin;
    out->length = end - begin;
    return out;
}

Not karakterlerin hiçbiri kopyalanacak var! String nesnesi değiştirilebilirse (karakterler daha sonra değişebilir), tüm karakterleri kopyalamanız gerekir, aksi takdirde alt dizideki karakterlerde yapılan değişiklikler daha sonra diğer dizeye yansıtılır.

Eşzamanlılık: Değişmez bir nesnenin iç yapısı geçerliyse, her zaman geçerli olacaktır. Farklı iş parçacıklarının bu nesne içinde geçersiz bir durum oluşturma şansı yoktur. Bu nedenle, değiştirilemeyen nesneler Thread Safe'tir .

Çöp toplama: Çöp toplayıcısının değişmez nesneler hakkında mantıklı kararlar alması çok daha kolaydır.

Bununla birlikte, değişmezliğin dezavantajları vardır:

Performans: Bekle, performansın değişmezliğin ters olduğunu söylediğini sanıyordum! Bazen, ama her zaman değil. Aşağıdaki kodu alın:

foo = foo.substring(0,4) + "a" + foo.substring(5);  // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder

İki çizgi de dördüncü karakteri "a" harfiyle değiştirir. İkinci kod sadece daha okunaklı olmakla kalmaz, aynı zamanda daha hızlıdır. Foo'nun altında yatan kodu nasıl yapmanız gerektiğine bakın. Alt dizeler kolaydır, ancak şimdi beşinci alanda zaten bir karakter olduğu ve başka bir şeyin foo'ya atıfta bulunabileceği için, onu değiştiremezsiniz; tüm dizeyi kopyalamanız gerekir (elbette bu işlevselliklerden bazıları gerçek C'deki işlevlere ayrılmıştır, ancak buradaki nokta, tek bir yerde yürütülen kodu göstermektir).

struct String* concatenate(struct String* first, struct String* second)
{
    struct String* new = malloc(sizeof(struct String));
    new->length = first->length + second->length;

    new->characters = malloc(new->length);

    int i;

    for(i = 0; i < first->length; i++)
        new->characters[i] = first->characters[i];

    for(; i - first->length < second->length; i++)
        new->characters[i] = second->characters[i - first->length];

    return new;
}

// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));

Birleştirme işleminin iki kez çağrıldığını , yani tüm dizenin döngü içinde olması gerektiğini unutmayın! Bunu barişlem için C koduyla karşılaştırın :

bar->characters[4] = 'a';

Değişken dize işlemi çok daha hızlıdır.

Sonuç: Çoğu durumda, değişmez bir dize istiyorsunuz. Ancak bir dizeye çok fazla ekleme ve ekleme yapmanız gerekiyorsa, hız için değişebilirliğe ihtiyacınız vardır. Eşzamanlılık güvenliği ve çöp toplama faydaları ile birlikte istiyorsanız, değişebilir nesnelerinizi bir yönteme yerel tutmaktır:

// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
    StringBuilder mutable;
    boolean first = true;

    for(int i = 0; i < strings.length; i++)
    {
        if(!first) first = false;
        else mutable.append(separator);

        mutable.append(strings[i]);
    }

    return mutable.toString();
}

Yana mutablenesne yerel referans, sen eşzamanlılık güvenliği konusunda endişelenmenize gerek yok (sadece bir dişin hiç dokunursa). Başka bir yere başvurulmadığından, yalnızca yığına ayrılır, bu nedenle işlev çağrısı biter bitmez dağıtılır (çöp toplama konusunda endişelenmenize gerek yoktur). Hem değişebilirliğin hem de değişmezliğin tüm performans avantajlarından faydalanırsınız.


4
Harika bir okuma! sadece bir şey ben (ilk) ve eğer (! ilk) değil olması gerektiğini düşünüyorum
Siddhartha

Gerekli olan alanların değişmez olması değil, nesnenin tanımlanmış gözlemlenebilir durumunun değişmez olmasıdır; içerdiği kapsülleme durumunun bir aracı olarak başka bir nesneye referans tutan bir nesne , ancak dış dünyaya maruz bıraktığı devletin tüm kapsüllenmiş yönleri aynı şekilde değişmezse değişmez olabilir. Alanların değişmez tipte olmasının ne gerekli ne de yeterli olduğuna dikkat edin. Önemli olan görünür durumdur.
supercat

7
Passing pointers because Java is pass-by-referenceJava "by-value" değil mi?
Cristian Gutu

@CristianGutu evet haklısın JAVA "REFERANS ile Pass" değil "Value by Pass"
Arsh Kaushal

Referans değer olarak geçer !!
devv

31

Aslında, yukarıda önerilen wikipedia tanımını kullanırsanız String değişmez.

Dizginin durumu yapım sonrası değişmektedir. Hashcode () yöntemine bir göz atın. Dize, hashcode değerini yerel bir alanda önbelleğe alır, ancak ilk hashcode () çağrısına kadar hesaplamaz. Hashcode'un bu tembel değerlendirmesi, String'i durumu değişen değişmez bir nesne olarak ilginç bir konuma yerleştirir, ancak yansıma kullanmadan değiştiği gözlemlenemez.

Dolayısıyla belki değişmez tanımının değiştiği gözlenemeyen bir nesne olmalıdır.

Durum, oluşturulduktan sonra değişmez bir nesnede değişirse, ancak kimse onu (yansıma olmadan) göremezse, nesne hala değişmez midir?


1
İyi fikir - gözlemlenemeyen bir nesne olduğu kadar dışarıdan değiştirmenin de bir yolu yoktur. HashCode () için özel alan, nesnenin harici olarak görünür durumuna önemli olmayan dahili bir değişikliktir.
mparaz

2
Aslında yansıma kullanırsanız değiştiği görülebilir . Yansıtmaya izin verirseniz Sedgewick's Strings daha fazla değişebilir .
Miguel

24

Değişmez nesneler, programlı olarak değiştirilemeyen nesnelerdir. Özellikle çok iş parçacıklı ortamlar veya bir nesnede birden fazla işlemin değiştirebildiği (değiştirebildiği) diğer ortamlar için iyidir.

Bununla birlikte, sadece açıklığa kavuşturmak için, StringBuilder değişmez bir nesne değil, aslında değiştirilebilir bir nesnedir. Normal bir Java Dizesi değişmezdir (yani oluşturulduktan sonra nesneyi değiştirmeden temel dizeyi değiştiremezsiniz).

Örneğin, bir String değeri ve bir String rengi olan ColoredString adlı bir sınıfım olduğunu varsayalım:

public class ColoredString {

    private String color;
    private String string;

    public ColoredString(String color, String string) {
        this.color  = color;
        this.string = string;
    }

    public String getColor()  { return this.color;  }
    public String getString() { return this.string; }

    public void setColor(String newColor) {
        this.color = newColor;
    }

}

Bu örnekte, yeni bir ColoredString sınıfı oluşturmadan anahtar özelliklerinden birini değiştirebildiğiniz (değiştirebildiğiniz) için ColoredString'in değiştirilebilir olduğu söyleniyor. Bunun kötü olmasının nedeni, örneğin, birden çok iş parçacığı içeren bir GUI uygulamanız olduğunu ve pencereye veri yazdırmak için ColoredStrings kullandığınızı varsayalım. Olarak oluşturulmuş bir ColoredString örneğiniz varsa

new ColoredString("Blue", "This is a blue string!");

Sonra dizenin her zaman "Mavi" olmasını beklersiniz. Ancak başka bir iş parçacığı bu örneği ele geçirip

blueString.setColor("Red");

"Mavi" bir tane istediğinizde aniden ve muhtemelen beklenmedik bir şekilde "Kırmızı" bir dizeye sahip olursunuz. Bu nedenle, nesnelerin etrafından geçerken değişmez nesneler neredeyse her zaman tercih edilir. Değişken nesnelerin gerçekten gerekli olduğu bir vakanız olduğunda, genellikle yalnızca kendi kontrol alanınızdan kopyalar geçirerek nesneyi koruyabilirsiniz.

Özetlemek gerekirse, Java, java.lang.String bir iletmenin nesne (öyle olamaz oluşturulduktan sonra değiştirilemez) ve java.lang.StringBuilder bunun yeni bir örneğini oluşturmadan değiştirilebilir çünkü değiştirilebilir bir nesne olduğunu.


Alanları salt okunur yapmalısınız. Şu anda sınıfınız kongre ile değişmez. Gelecekteki geliştiricilere, değişmez olanın kasıtlı olduğuna dair bir gösterge yoktur. Alanları salt okunur yapmak, gelecekteki bir dev için niyetinizi açıklığa kavuşturacaktır
JaredPar

@JaredPar - Aslında, sınıf hiç değişmez değil ... bunun neden bir sorun olabileceğini göstermek için değişebilir bir sınıf örneği.
Jason Coco

1
@JaredPar - Oh, bu tamamen sorun değil :) Daha net olması için biraz yeniden yazacaktım, ama Douglas'ın zaten iyi yazılmış ve favori gibi görünüyor, bu yüzden başka bir örnek olarak benimkini bırakacağım; ama birisi gerçekten eğlenceli olduğunu düşündüğüm özellikleri final yapmak için düzenledi :)
Jason Coco

24
  1. Büyük uygulamalarda, dize değişmezlerinin büyük bellek bitlerini işgal etmesi yaygındır. Böylece bellek verimli bir şekilde işlemek için, JVM "String sabit havuz" adlı bir alan ayırır. aksine, en fazla sekiz acil bayt gerekir )
  2. Complier bir String değişmezine rastladığında, zaten aynı olan bir değişmez değerin olup olmadığını görmek için havuzu denetler. Ve bir tane bulunursa, yeni değişmeze başvuru mevcut Dize'ye yönlendirilir ve yeni bir 'Dize değişmez nesnesi' oluşturulmaz (mevcut Dize yalnızca ek bir başvuru alır).
  3. Bu nedenle: Dize değiştirilebilirliği belleği korur ...
  4. Ama değişkenlerden herhangi biri değeri değiştirdiğinde, Aslında - sadece referansları değişti, hafızadaki değer değil (dolayısıyla referans veren diğer değişkenleri etkilemeyecek) ....

String s1 = "Eski dize";

//s1 variable, refers to string in memory
        reference                 |     MEMORY       |
        variables                 |                  |

           [s1]   --------------->|   "Old String"   |

Dize s2 = s1;

//s2 refers to same string as s1
                                  |                  |
           [s1]   --------------->|   "Old String"   |
           [s2]   ------------------------^

s1 = "Yeni Dize";

//s1 deletes reference to old string and points to the newly created one
           [s1]   -----|--------->|   "New String"   |
                       |          |                  |
                       |~~~~~~~~~X|   "Old String"   |
           [s2]   ------------------------^

'Bellekteki' orijinal dize değişmedi, ancak başvuru değişkeni, yeni dizeyi gösterecek şekilde değiştirildi. Ve eğer s2'miz olmasaydı, "Old String" hala bellekte olurdu ama ona erişemeyiz ...


16

"değişmez", değeri değiştiremeyeceğiniz anlamına gelir. String sınıfının bir örneğine sahipseniz, çağırdığınız değeri değiştirmiş görünen herhangi bir yöntem aslında başka bir String oluşturur.

String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"

Değişiklikleri korumak için böyle bir şey yapmalısınız foo = foo.sustring (3);

Koleksiyonlarla çalışırken değişmez veya değişmez komik olabilir. Harita için bir anahtar olarak mutable nesneyi kullanırsanız ne olacağını düşünün ve sonra değeri değiştirin (ipucu: düşünün equalsve hashCode).


13

java.time

Biraz gecikmiş olabilir ama değişmez bir nesnenin ne olduğunu anlamak için yeni Java 8 Tarih ve Saat API'sinden ( java.time ) aşağıdaki örneği düşünün . Muhtemelen bildiğiniz gibi Java 8'deki tüm tarih nesneleri değiştirilemez, bu nedenle aşağıdaki örnekte

LocalDate date = LocalDate.of(2014, 3, 18); 
date.plusYears(2);
System.out.println(date);

Çıktı:

2014/03/18

Bu, başlangıç ​​tarihi ile aynı yılı yazdırır, çünkü plusYears(2)yeni bir nesne döndürür, böylece eski tarih değişmez bir nesne olduğu için hala değişmez. Oluşturulduktan sonra bunu daha fazla değiştiremezsiniz ve tarih değişkeni hala onu gösterir.

Bu nedenle, bu kod örneği o çağrıyla başlatılan ve döndürülen yeni nesneyi yakalamalı ve kullanmalıdır plusYears.

LocalDate date = LocalDate.of(2014, 3, 18); 
LocalDate dateAfterTwoYears = date.plusYears(2);

date.toString ()… 2014-03-18

dateAfterTwoYears.toString ()… 2016-03-18


8

Java 5 Study Guide için SCJP Sun Sertifikalı Programcı'nın açıklamasını gerçekten çok seviyorum .

Java'yı bellekte daha verimli hale getirmek için JVM, "String sabit havuzu" adı verilen özel bir bellek alanı ayırır. Derleyici bir String değişmeziyle karşılaştığında, özdeş bir String olup olmadığını görmek için havuzu denetler. Bir eşleşme bulunursa, yeni değişmeze yapılan başvuru mevcut Dize'ye yönlendirilir ve yeni bir String değişmezi nesnesi oluşturulmaz.


Bunu herhangi bir özdeş değişmez nesne ile yapabilmelidir, ancak sanırım bu çok fazla çalışma zamanı alacaktı.
Zan Lynx

8

Değişmez olan nesneler, yaratıldıktan sonra durumlarını değiştiremezler.

Mümkün olduğunca değişmez nesneleri kullanmanın üç ana nedeni vardır; bunların tümü, kodunuzda tanıttığınız hataların sayısını azaltmaya yardımcı olur:

  • Bir nesnenin durumunun başka bir yöntemle değiştirilemeyeceğini bildiğinizde programınızın nasıl çalıştığına karar vermek çok daha kolaydır
  • Değişmez nesneler otomatik olarak iş parçacığı açısından güvenlidir (güvenli bir şekilde yayınlandıkları varsayılarak), bu nedenle sabitlenmesi zor çoklu iş parçacığı hatalarının nedeni asla olmayacaktır.
  • Değişmez nesneler her zaman aynı Hash koduna sahip olacaktır, bu nedenle bir HashMap (veya benzeri) içindeki anahtarlar olarak kullanılabilirler. Bir karma tablosundaki bir öğenin karma kodu değişecek olsaydı, tablo girdisini etkin bir şekilde kaybederdi, çünkü tabloda bulma girişimleri yanlış yere bakacaktır. String nesnelerinin değiştirilememesinin ana nedeni budur - genellikle HashMap anahtarları olarak kullanılırlar.

Ayrıca, bir nesnenin durumunun değişmez olduğunu bildiğiniz zaman kodda yapabileceğiniz başka optimizasyonlar da vardır - örneğin, hesaplanan hasarı önbelleğe almak - ancak bunlar optimizasyonlardır ve bu nedenle neredeyse o kadar ilginç değildir.


5

Bir anlamı, değerin bilgisayarda nasıl saklandığı ile ilgilidir, Örneğin .Net dizesi için, bellekteki dizenin değiştirilemeyeceği anlamına gelir, Değiştirdiğinizi düşündüğünüzde, aslında yeni bir bellekteki dize ve mevcut değişkeni (başka bir yerde gerçek karakter koleksiyonuna yalnızca bir işaretçi) yeni dizeye işaret eder.


4
String s1="Hi";
String s2=s1;
s1="Bye";

System.out.println(s2); //Hi  (if String was mutable output would be: Bye)
System.out.println(s1); //Bye

s1="Hi": s1içinde "Hi" değeri olan bir nesne yaratıldı.

s2=s1 : s2s1 nesnesine başvurularak bir nesne oluşturulur.

s1="Bye": dize türü ve Dize türü değişmez bir tür s1olduğundan s1, önceki nesnenin değeri değişmez, bunun yerine derleyici "Bye" değeriyle yeni bir String nesnesi oluşturur ve s1ona başvurur . burada s2değer yazdırdığımızda , sonuç "Merhaba" değil "Merhaba" olur, çünkü "Merhaba" değeri olan s2önceki s1nesneye başvurulur .


biraz açıklama ekleyebilir misiniz lütfen?
minigeek

3

Değişmez, nesne oluşturulduktan sonra üye olmayanların değişeceği anlamına gelir. Stringdeğiştirilemez çünkü içeriğini değiştiremezsiniz. Örneğin:

String s1 = "  abc  ";
String s2 = s1.trim();

Yukarıdaki kodda, s1 dizesi değişmedi, kullanılarak başka bir nesne ( s2) oluşturuldu s1.


3

Değişmez, basitçe değiştirilemez ya da değiştirilemez anlamına gelir. String nesnesi oluşturulduktan sonra verileri veya durumu değiştirilemez

Aşağıdaki örneği düşünelim,

class Testimmutablestring{  
  public static void main(String args[]){  
    String s="Future";  
    s.concat(" World");//concat() method appends the string at the end  
    System.out.println(s);//will print Future because strings are immutable objects  
  }  
 }  

Aşağıdaki diyagramı düşünerek fikir edelim,

resim açıklamasını buraya girin

Bu şemada, "Gelecek Dünyası" olarak yaratılmış yeni bir nesne görebilirsiniz. Ama "Gelecek" i değiştirmeyin. Because String is immutable. s, hala "Gelecek" e bakın. "Gelecek Dünyası" adını vermeniz gerekiyorsa,

String s="Future";  
s=s.concat(" World");  
System.out.println(s);//print Future World

Dize nesneleri neden Java'da değiştirilemez?

Çünkü Java dize hazır bilgisi kavramını kullanır. 5 referans değişkeni olduğunu varsayalım, hepsi tek bir nesneyi "Gelecek" olarak ifade eder. Bir referans değişkeni nesnenin değerini değiştirirse, tüm referans değişkenlerinden etkilenecektir. Bu nedenle dize nesneleri java'da değişmezdir.


2

Bir kez örneklendikten sonra değiştirilemez. Bir örneğinin karma veya benzeri bir anahtarın anahtarı olarak kullanılabileceğini düşünün. Java en iyi uygulamalarına göz atın.


0

Değişmez Nesneler

Bir nesne, inşa edildikten sonra durumu değişemezse değişmez olarak kabul edilir. Değişmez nesnelere maksimum güven, basit ve güvenilir kod oluşturmak için sağlam bir strateji olarak kabul edilmektedir.

Değişmez nesneler özellikle eşzamanlı uygulamalarda kullanışlıdır. Durumu değiştiremedikleri için, iplik girişimi ile bozulamazlar veya tutarsız bir durumda gözlemlenemezler.

Programcılar genellikle değişmez nesneleri kullanma konusunda isteksizdir, çünkü yerinde bir nesneyi güncellemenin aksine yeni bir nesne yaratmanın maliyeti konusunda endişe duyarlar. Nesne yaratmanın etkisi genellikle fazla tahmin edilir ve değişmez nesnelerle ilişkili bazı verimliliklerle dengelenebilir. Bunlar, çöp toplama nedeniyle azalan ek yükü ve değişken nesneleri bozulmaya karşı korumak için gerekli kodun kaldırılmasını içerir.

Aşağıdaki alt bölümler, örnekleri değişebilen bir sınıfı alır ve ondan değişmeyen örnekleri olan bir sınıf türetir. Bunu yaparken, bu tür dönüşüm için genel kurallar verir ve değişmez nesnelerin bazı avantajlarını gösterirler.

Kaynak


0

Kabul edilen cevap tüm sorulara cevap vermediğinden. 11 yıl 6 ay sonra cevap vermeye zorlandım.

Birisi değişmez ile ne kastedildiğini açıklığa kavuşturabilir mi?

Umarım değişmez nesne demek istediniz (çünkü değişmez referansı düşünebiliriz ).

Bir nesne değiştirilemez : iff oluşturulduktan sonra her zaman aynı değeri temsil ederler (değeri değiştiren herhangi bir yöntemi yoktur).

Neden Stringdeğişmez?

Sting.java kaynak koduna bakarak kontrol edilebilen yukarıdaki tanıma uyun .

Değişmez cisimlerin avantajları / dezavantajları nelerdir? değişmez tipler:

  • böcek daha güvenli.

  • anlaşılması daha kolay.

  • ve değişime daha hazır.

Neden StringBuilder gibi değişken bir nesne String ve tam tersine tercih edilmeli?

Soruyu daraltmak Programlamada neden değiştirilebilir StringBuilder'a ihtiyacımız var? Bunun yaygın bir kullanımı, çok sayıda dizeyi bir araya getirmektir, örneğin:

String s = "";
for (int i = 0; i < n; ++i) {
    s = s + n;
}

Değişmez dizeler kullanarak, bu çok sayıda geçici kopya oluşturur - dizenin ilk sayısı ("0") son dizgiyi oluştururken n kez kopyalanır, ikinci sayı n-1 kez kopyalanır ve böylece üzerinde. Sadece n öğeyi birleştirmiş olsak da, tüm bu kopyalamayı yapmak aslında O (n2) zamanına mal olur.

StringBuilder bu kopyalamayı en aza indirecek şekilde tasarlanmıştır. Bir toString () çağrısıyla son Dizeyi istediğinizde, sonuna kadar herhangi bir kopyalama yapmaktan kaçınmak için basit ama akıllı bir iç veri yapısı kullanır:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
  sb.append(String.valueOf(n));
}
String s = sb.toString();

İyi performans elde etmek, değiştirilebilir nesneleri kullanmamızın bir nedenidir. Bir diğeri uygun paylaşımdır: programınızın iki bölümü ortak bir değişken veri yapısını paylaşarak daha rahat iletişim kurabilir.

Daha fazlası burada bulunabilir: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types


-1

Değişmez bir nesne, oluşturduktan sonra değiştiremeyeceğiniz nesnedir. Tipik bir örnek dizgi değişmez değerleridir.

Giderek daha popüler hale gelen AD programlama dili, "değişmez" anahtar kelimeyle "değişmezlik" kavramına sahiptir. Dr.Dobb'un bu konudaki makalesine bakın - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Sorunu mükemmel bir şekilde açıklıyor.


D 2.020 itibariyle anahtar kelimenin değişmezden değiştirilemez hale geldiğine inanıyorum. Bir nokta görmüyorum, ama "şimdi değişmez uygulandı" der. digitalmars.com/d/2.0/changelog.html#new2_020
he_the_great
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.