Waarom is stringbuffer definitief?

De stringklasse is onveranderbaar en een van de redenen daarvoor is dat de klasse als definitief wordt verklaard, maar er zijn ook andere redenen. Maar waarom is StringBuffer of StringBuilder definitief en toch kunnen ze worden gewijzigd? Dus welke andere factoren bepalen dat String onveranderlijk is?

2
@jdphenix voor een klasse die echt onveranderlijk is, moet definitief zijn, om uitbreiding te vermijden om mutatie toe te voegen
toegevoegd de auteur Steve Kuo, de bron
@jdphenix voor een klasse die echt onveranderlijk is, moet definitief zijn, om uitbreiding te vermijden om mutatie toe te voegen
toegevoegd de auteur Steve Kuo, de bron
@JBNizet: ik weet niet zeker of de laatste zin echt klopt; het maken van pakket-private en alleen het aanbieden van package-private onveranderlijke subklassen (a la ImmutableList ) is ook voldoende.
toegevoegd de auteur Louis Wasserman, de bron
@JBNizet: ik weet niet zeker of de laatste zin echt klopt; het maken van pakket-private en alleen het aanbieden van package-private onveranderlijke subklassen (a la ImmutableList ) is ook voldoende.
toegevoegd de auteur Louis Wasserman, de bron
Een onveranderlijke klasse is een klasse waarvan de instantie niet kan veranderen nadat ze zijn geconstrueerd. Een laatste klas is een klasse die niet kan worden verlengd. Dat zijn bijna orthogonale concepten. De enige link tussen beide is dat onveranderbare klassen definitief zijn, zodat je geen subklassen kunt maken die een veranderlijke status aan de basisklasse zouden toevoegen.
toegevoegd de auteur JB Nizet, de bron
@LouisWasserman overeengekomen. Ik bedoelde niet dat het maken van de klassenfinale de enige manier was om te voorkomen dat subklassen een veranderlijke status toevoegden. Wat ik bedoelde, is dat wanneer een onveranderlijk besluit definitief te zijn, de reden is om te voorkomen dat subklassen een veranderlijke toestand toevoegen. Je bewijst mijn punt zelfs nog meer: ​​onveranderlijkheid en laatste klassen zijn orthogonale concepten: een klasse kan onveranderlijk zijn zonder definitief te zijn, en een laatste klasse kan veranderlijk zijn.
toegevoegd de auteur JB Nizet, de bron
@LouisWasserman overeengekomen. Ik bedoelde niet dat het maken van de klassenfinale de enige manier was om te voorkomen dat subklassen een veranderlijke status toevoegden. Wat ik bedoelde, is dat wanneer een onveranderlijk besluit definitief te zijn, de reden is om te voorkomen dat subklassen een veranderlijke toestand toevoegen. Je bewijst mijn punt zelfs nog meer: ​​onveranderlijkheid en laatste klassen zijn orthogonale concepten: een klasse kan onveranderlijk zijn zonder definitief te zijn, en een laatste klasse kan veranderlijk zijn.
toegevoegd de auteur JB Nizet, de bron
Een onveranderlijke klasse is een klasse waarvan de instantie niet kan veranderen nadat ze zijn geconstrueerd. Een laatste klas is een klasse die niet kan worden verlengd. Dat zijn bijna orthogonale concepten. De enige link tussen beide is dat onveranderbare klassen definitief zijn, zodat je geen subklassen kunt maken die een veranderlijke status aan de basisklasse zouden toevoegen.
toegevoegd de auteur JB Nizet, de bron
Ik denk dat je het concept van final , dat wil zeggen niet-uitbreidbaarheid en onveranderlijk, in de war kan brengen.
toegevoegd de auteur jdphenix, de bron
@abhilash Ik denk dat dit kan helpen begrijpen docs.oracle.com/javase/ handleiding/essentieel/concurrency/& hellip;
toegevoegd de auteur jdphenix, de bron
@abhilash Ik denk dat dit kan helpen begrijpen docs.oracle.com/javase/ handleiding/essentieel/concurrency/& hellip;
toegevoegd de auteur jdphenix, de bron
@SteveKuo Ik ben het ermee eens. abhilash lijkt te geloven dat ze geloven dat een laatste klasse inherent onveranderlijk is, wat duidelijk niet correct is. Ik heb misschien verkeerd gelezen.
toegevoegd de auteur jdphenix, de bron
@SteveKuo Ik ben het ermee eens. abhilash lijkt te geloven dat ze geloven dat een laatste klasse inherent onveranderlijk is, wat duidelijk niet correct is. Ik heb misschien verkeerd gelezen.
toegevoegd de auteur jdphenix, de bron
Dus wat is jouw vraag nu? Wilt u weten waarom StringBuilder etc. definitief is of wilt u weten wat String onveranderlijk maakt?
toegevoegd de auteur Holger, de bron
Dus wat is jouw vraag nu? Wilt u weten waarom StringBuilder etc. definitief is of wilt u weten wat String onveranderlijk maakt?
toegevoegd de auteur Holger, de bron
toegevoegd de auteur cDima, de bron
toegevoegd de auteur cDima, de bron
@jdphenix Ik weet wat een laatste modifier doet voor een klasse, maar ik verward op basis van welke reden String-klasse onveranderbaar is, omdat overal ze de finale zeggen. Maar ook StringBuffer is definitief, dus welke andere factor?
toegevoegd de auteur Abhilash28, de bron
@jdphenix Ik weet wat een laatste modifier doet voor een klasse, maar ik verward op basis van welke reden String-klasse onveranderbaar is, omdat overal ze de finale zeggen. Maar ook StringBuffer is definitief, dus welke andere factor?
toegevoegd de auteur Abhilash28, de bron

13 antwoord

StringBuffer and StringBuilder are mainly used for string concatenating operations within a single method, the code using them often being generating by the compiler. So being extended is not the typical use case.

Aan de andere kant zorgt het zijn van final voor betere optimalisaties binnen een JVM, althans in het verleden; De HotSpot JVM van vandaag heeft dit niet nodig, maar er is nooit een reden geweest om de definitieve -verklaring van deze klassen te wijzigen.

Houd er rekening mee dat uitbreiding van StringBuilder en het negeren van methoden voor polymorf gedrag een beetje zinloos is omdat er geen openbare -methode is binnen de gehele JRE die StringBuilder accepteert of retourneert instance (behalve in StringBuilder zelf). Er zijn Aan te vullen en CharSequence dit gat opvullen en veel meer flexibiliteit bieden.

De begrippen mutability en immutability zijn geheel verschillend van het concept van final klassen. Ze zijn eenvoudigweg afhankelijk van wat voor soort methoden of bewerkingen een klasse biedt. String heeft geen methoden waarmee de inhoud kan worden gewijzigd, terwijl StringBuffer en StringBuilder dergelijke methoden hebben. Het declareren van een onveranderlijke klasse definitief helpt alleen bij het verbieden van subklassen die methoden kunnen introduceren die mutatie ondersteunen, maar dat is geen moeilijke vereiste.

3
toegevoegd

Waarom String definitief en onveranderlijk is, zijn eigenlijk twee , gedeeltelijk onafhankelijke, vragen.

Ten eerste maakt String deel uit van het java.lang-pakket, omdat de naam suggereert dat de typen in dit pakket gerelateerd zijn aan het implementeren van de java-taal in de definitie . Dat is een reden waarom het definitief is, als ik een tekenreeks ergens neem waar < erop staat om zich te gedragen als de Java-taal die is gedefinieerd als een tekenreeks ( omdat je je eigen subklasse met ander gedrag niet kunt maken).

Ten tweede, de onveranderlijkheid van String is "slechts" een ontwerpkeuze, maar het heeft gunstige implicaties in dat, wanneer je ergens een String doorgeeft (bijvoorbeeld als een Bestandsnaam), de API die wordt genoemd zeker kan zijn dat je de string niet kunt veranderen en bewaar er direct verwijzingen naar (in plaats van een kopie ervan te maken als het veranderbaar is). Het vereenvoudigt ook aanzienlijk het werken met String in multithread-omgevingen.

Dus waarom is StringBuilder/Buffer definitief? Dit is wederom "slechts" een ontwerpkeuze, maar er zijn geen sterke en voor de hand liggende rechtvaardigingen achter als er zijn voor String. Ze deden het gewoon zo.

2
toegevoegd

Waarom String definitief en onveranderlijk is, zijn eigenlijk twee , gedeeltelijk onafhankelijke, vragen.

Ten eerste maakt String deel uit van het java.lang-pakket, omdat de naam suggereert dat de typen in dit pakket gerelateerd zijn aan het implementeren van de java-taal in de definitie . Dat is een reden waarom het definitief is, als ik een tekenreeks ergens neem waar < erop staat om zich te gedragen als de Java-taal die is gedefinieerd als een tekenreeks ( omdat je je eigen subklasse met ander gedrag niet kunt maken).

Ten tweede, de onveranderlijkheid van String is "slechts" een ontwerpkeuze, maar het heeft gunstige implicaties in dat, wanneer je ergens een String doorgeeft (bijvoorbeeld als een Bestandsnaam), de API die wordt genoemd zeker kan zijn dat je de string niet kunt veranderen en bewaar er direct verwijzingen naar (in plaats van een kopie ervan te maken als het veranderbaar is). Het vereenvoudigt ook aanzienlijk het werken met String in multithread-omgevingen.

Dus waarom is StringBuilder/Buffer definitief? Dit is wederom "slechts" een ontwerpkeuze, maar er zijn geen sterke en voor de hand liggende rechtvaardigingen achter als er zijn voor String. Ze deden het gewoon zo.

2
toegevoegd

Ik denk dat je een misvatting hebt over het "definitieve" sleutelwoord wanneer het gebruikt wordt met de les. Wanneer een variabele definitief wordt verklaard, kan de waarde ervan niet worden gewijzigd nadat deze is geïnitialiseerd.

d.w.z.

final int i=5;
      i++// Will give an error.

Maar:

In case of classes: Final keyword servers the purpose of making the class non-inheritable d.w.z.that class can't be sub-classed!. i.e.

final class question
{}
class answer extends question//Will give an error!!!
{}

Antwoord op uw vraag:

Nu heb je gelijk dat string onveranderbaar is, want als een stringobject eenmaal is geïnitialiseerd, kan het niet worden gewijzigd en kunnen Stringbuilder en Stringbuffer niet veranderen (Vice-Versa), en dit heeft niets te maken met het feit dat deze klassen definitief zijn! Je onderwerpt ze niet goed!

Ik hoop dat ik geholpen heb!

Bewerken

Ik denk dat ik dit volledig moet uitleggen dat Stringbuilder veranderlijk is en String niet is:

Ik zal deze code per code uitleggen:

Stringbuilder a = new Stringbuilder("a");//Initial String!!
a.append("b"); //Now the String is ab!!

So, since the same object d.w.z.a got its value changed it is known as mutable.(An object d.w.z.capable of changing its value after being initialized).

Now-reeks:

String a = "a";
a = a + "b"; //Explained below.

Hoewel dit voor u kan lijken, verandert string-object a zijn waarde en is het dus veranderlijk, maar dat is het niet, want achter de schermen werkt Stringbuilder. d.w.z. het daadwerkelijke ding deed door compiler in de bovengenoemde code is:

a = new StringBuilder(a.append("b")); //The actual code...

So, now the variable a stores the values "ab". I know this is confusing, but if you read my code precisely you will see that the object a never changed it's values it just got assigned a new value!! This is what is known as being immutable d.w.z.an object cant change after being initialized!

Ik hoop dat ik geholpen heb

1
toegevoegd
En als u vraagt ​​hoe klasse van snaren onveranderlijk is, is het antwoord heel eenvoudig! De gegevensleden binnen de klasse java.lang.String zijn definitief !!!!
toegevoegd de auteur Kaushal Jain, de bron
En merk op dat hoewel ik hierboven heb gespecificeerd dat de variabele a de waarde "ab" opslaat, de variabelen in java geen enkele waarde opslaan !. Ze slaan alleen de geheugenreferentie op van het object dat feitelijk in het geheugen is opgeslagen (gemaakt met een "nieuw" sleutelwoord). Ik zei net dat om eenvoudig te zijn in uitleg!
toegevoegd de auteur Kaushal Jain, de bron
Ik hoop dat je mijn bewerking hebt gezien!
toegevoegd de auteur Kaushal Jain, de bron
@abhilash: geen mutatie-methoden blootleggen, subklassen verbieden en garanderen dat de resultaten van methoden altijd hetzelfde zijn.
toegevoegd de auteur Louis Wasserman, de bron
Maar wat maakt het dan onveranderlijk?
toegevoegd de auteur Abhilash28, de bron

Ik denk dat je een misvatting hebt over het "definitieve" sleutelwoord wanneer het gebruikt wordt met de les. Wanneer een variabele definitief wordt verklaard, kan de waarde ervan niet worden gewijzigd nadat deze is geïnitialiseerd.

d.w.z.

final int i=5;
      i++// Will give an error.

Maar:

In case of classes: Final keyword servers the purpose of making the class non-inheritable d.w.z.that class can't be sub-classed!. i.e.

final class question
{}
class answer extends question//Will give an error!!!
{}

Antwoord op uw vraag:

Nu heb je gelijk dat string onveranderbaar is, want als een stringobject eenmaal is geïnitialiseerd, kan het niet worden gewijzigd en kunnen Stringbuilder en Stringbuffer niet veranderen (Vice-Versa), en dit heeft niets te maken met het feit dat deze klassen definitief zijn! Je onderwerpt ze niet goed!

Ik hoop dat ik geholpen heb!

Bewerken

Ik denk dat ik dit volledig moet uitleggen dat Stringbuilder veranderlijk is en String niet is:

Ik zal deze code per code uitleggen:

Stringbuilder a = new Stringbuilder("a");//Initial String!!
a.append("b"); //Now the String is ab!!

So, since the same object d.w.z.a got its value changed it is known as mutable.(An object d.w.z.capable of changing its value after being initialized).

Now-reeks:

String a = "a";
a = a + "b"; //Explained below.

Hoewel dit voor u kan lijken, verandert string-object a zijn waarde en is het dus veranderlijk, maar dat is het niet, want achter de schermen werkt Stringbuilder. d.w.z. het daadwerkelijke ding deed door compiler in de bovengenoemde code is:

a = new StringBuilder(a.append("b")); //The actual code...

So, now the variable a stores the values "ab". I know this is confusing, but if you read my code precisely you will see that the object a never changed it's values it just got assigned a new value!! This is what is known as being immutable d.w.z.an object cant change after being initialized!

Ik hoop dat ik geholpen heb

1
toegevoegd
En als u vraagt ​​hoe klasse van snaren onveranderlijk is, is het antwoord heel eenvoudig! De gegevensleden binnen de klasse java.lang.String zijn definitief !!!!
toegevoegd de auteur Kaushal Jain, de bron
En merk op dat hoewel ik hierboven heb gespecificeerd dat de variabele a de waarde "ab" opslaat, de variabelen in java geen enkele waarde opslaan !. Ze slaan alleen de geheugenreferentie op van het object dat feitelijk in het geheugen is opgeslagen (gemaakt met een "nieuw" sleutelwoord). Ik zei net dat om eenvoudig te zijn in uitleg!
toegevoegd de auteur Kaushal Jain, de bron
Ik hoop dat je mijn bewerking hebt gezien!
toegevoegd de auteur Kaushal Jain, de bron
@abhilash: geen mutatie-methoden blootleggen, subklassen verbieden en garanderen dat de resultaten van methoden altijd hetzelfde zijn.
toegevoegd de auteur Louis Wasserman, de bron
Maar wat maakt het dan onveranderlijk?
toegevoegd de auteur Abhilash28, de bron

String is not immutable because it is final; final and immutability are more or less orthogonal. Making a class final is part of one approach to making a class immutable, but making a class final is also part of a good programming practice in general no matter what behavior you want for the class.

Een onveranderlijke klasse mag niet worden uitbesteed door externe gebruikers. Het kan verschillende implementaties hebben binnen zijn eigen pakket, zoals b.v. Guava's ImmutableMap , in welk geval de klasse niet definitief hoeft te zijn, maar je kunt ook de extensie verbieden door bijv. constructors package-private maken zodat gebruikers buiten het pakket de klasse niet kunnen uitbreiden.

Een final -klasse is elke klasse die niet kan worden uitgebreid. Dit wordt aanbevolen in veel gevallen in Effective Java - dat wil zeggen dat wanneer u geen expliciete reden hebt om de klasse subklasse te maken, het in het algemeen de goede gewoonte is om deze definitief te maken.

1
toegevoegd

String is not immutable because it is final; final and immutability are more or less orthogonal. Making a class final is part of one approach to making a class immutable, but making a class final is also part of a good programming practice in general no matter what behavior you want for the class.

Een onveranderlijke klasse mag niet worden uitbesteed door externe gebruikers. Het kan verschillende implementaties hebben binnen zijn eigen pakket, zoals b.v. Guava's ImmutableMap , in welk geval de klasse niet definitief hoeft te zijn, maar je kunt ook de extensie verbieden door bijv. constructors package-private maken zodat gebruikers buiten het pakket de klasse niet kunnen uitbreiden.

Een final -klasse is elke klasse die niet kan worden uitgebreid. Dit wordt aanbevolen in veel gevallen in Effective Java - dat wil zeggen dat wanneer u geen expliciete reden hebt om de klasse subklasse te maken, het in het algemeen de goede gewoonte is om deze definitief te maken.

1
toegevoegd

StringBuffer was the concept of mutable String, that is thread-safe, that is, all operations performed on it are synchronized.

StringBuilder is recommended replacement for StringBuffer. It was introduced, when it came out, that synchronization is not used very often, when it comes to Strings.

String is just String. Why is it immutable? Perhaps the reason was thread-safety and cost of such. What if you want to store global String, that is read only? If it was mutable, then all reads must have been synchronized - an additional overhead, that is not necessary here.

Daarom zijn deze drie klassen beschikbaar gesteld - u heeft gekozen waarvoor u wilt betalen.

Zoals u hebt opgemerkt, zijn al deze klassen - String , StringBuilder en StringBuffer definitief. De reden hiervoor is dat u het gedrag van deze klassen niet kunt (en zou moeten) wijzigen.

Het is beter om een ​​andere klasse te implementeren, die (bijvoorbeeld) StringBuilder bevat en vergelijkbare functionaliteit biedt, dan deze uit te breiden.

Als je wilt, kun je vergelijkbare functionaliteit bieden door CharSequence - al deze klassen implementeren deze interface.

0
toegevoegd

StringBuffer was the concept of mutable String, that is thread-safe, that is, all operations performed on it are synchronized.

StringBuilder is recommended replacement for StringBuffer. It was introduced, when it came out, that synchronization is not used very often, when it comes to Strings.

String is just String. Why is it immutable? Perhaps the reason was thread-safety and cost of such. What if you want to store global String, that is read only? If it was mutable, then all reads must have been synchronized - an additional overhead, that is not necessary here.

Daarom zijn deze drie klassen beschikbaar gesteld - u heeft gekozen waarvoor u wilt betalen.

Zoals u hebt opgemerkt, zijn al deze klassen - String , StringBuilder en StringBuffer definitief. De reden hiervoor is dat u het gedrag van deze klassen niet kunt (en zou moeten) wijzigen.

Het is beter om een ​​andere klasse te implementeren, die (bijvoorbeeld) StringBuilder bevat en vergelijkbare functionaliteit biedt, dan deze uit te breiden.

Als je wilt, kun je vergelijkbare functionaliteit bieden door CharSequence - al deze klassen implementeren deze interface.

0
toegevoegd

Dus welke andere factoren bepalen waarom String onveranderlijk is?

Het antwoord is simpel, omdat al het gegevenslid van de klasse String definitief is, waardoor het even onveranderlijk is.

Als u uw eigen klasse onveranderlijk wilt maken, maakt u alle gegevensleden van die klasse als definitief. En initialiseer alle uiteindelijke gegevensleden in de constructor, zodat ze, als ze eenmaal zijn geïnitialiseerd, nooit zijn gewijzigd.

Als u de implementatie van de String -klasse voor onveranderlijkheid ziet, vindt u:

private final char[] value;

En initialisatie van waarde zal plaatsvinden in constructor deel:

public String(String toCopy){

     value = toCopy.value;

}

En als u de implementatie van de StringBuffer -klasse ziet, vindt u:

private char[] value;

public StringBuffer(String toCopy){

     value = toCopy.value;

}

In de bovenstaande code kunt u zien dat de String -klasse het waarde -datalid eenmaal wordt geïnitialiseerd en nooit zal veranderen, maar dat de StringBuffer -klasse waarde data-lid kan vele keren worden geïnitialiseerd en gewijzigd.

Dit maakt klasse String dus onveranderlijk en maakt geen klassefinitie.

0
toegevoegd

Dus welke andere factoren bepalen waarom String onveranderlijk is?

Het antwoord is simpel, omdat al het gegevenslid van de klasse String definitief is, waardoor het even onveranderlijk is.

Als u uw eigen klasse onveranderlijk wilt maken, maakt u alle gegevensleden van die klasse als definitief. En initialiseer alle uiteindelijke gegevensleden in de constructor, zodat ze, als ze eenmaal zijn geïnitialiseerd, nooit zijn gewijzigd.

Als u de implementatie van de String -klasse voor onveranderlijkheid ziet, vindt u:

private final char[] value;

En initialisatie van waarde zal plaatsvinden in constructor deel:

public String(String toCopy){

     value = toCopy.value;

}

En als u de implementatie van de StringBuffer -klasse ziet, vindt u:

private char[] value;

public StringBuffer(String toCopy){

     value = toCopy.value;

}

In de bovenstaande code kunt u zien dat de String -klasse het waarde -datalid eenmaal wordt geïnitialiseerd en nooit zal veranderen, maar dat de StringBuffer -klasse waarde data-lid kan vele keren worden geïnitialiseerd en gewijzigd.

Dit maakt klasse String dus onveranderlijk en maakt geen klassefinitie.

0
toegevoegd

Als u zich zorgen maakt over het uitbreiden van het gedrag van StringBuilder of StringBuffer, kunt u het nog steeds doen - gewoon niet door overerving. Je kunt je samenstelling of delegatie. Classes String, StringBuffer, StringBuilder alle implement CharacterSequence. Dus maak je klasse die CharacterSequence implementeert en delegeer alle methoden naar de samengestelde StringBuffer of StringBuilder. Compositie over Inheritance is de gouden regel in GoF - zie dit discussie ook.

Een klassement finaliseren is een extra en krachtiger inkapselinglaag - misschien vindt de auteur van de code niet dat iemand het gedrag bij uitbreiding moet aanpassen, omdat hij/zij een subklasse van de betreffende klasse mogelijk niet echt representatief voor zelf (in termen van conversie).

0
toegevoegd

Als u zich zorgen maakt over het uitbreiden van het gedrag van StringBuilder of StringBuffer, kunt u het nog steeds doen - gewoon niet door overerving. Je kunt je samenstelling of delegatie. Classes String, StringBuffer, StringBuilder alle implement CharacterSequence. Dus maak je klasse die CharacterSequence implementeert en delegeer alle methoden naar de samengestelde StringBuffer of StringBuilder. Compositie over Inheritance is de gouden regel in GoF - zie dit discussie ook.

Een klassement finaliseren is een extra en krachtiger inkapselinglaag - misschien vindt de auteur van de code niet dat iemand het gedrag bij uitbreiding moet aanpassen, omdat hij/zij een subklasse van de betreffende klasse mogelijk niet echt representatief voor zelf (in termen van conversie).

0
toegevoegd