Waarom is String onveranderlijk in Java?

1. Inleiding

In Java zijn strings onveranderlijk. Een voor de hand liggende vraag die vrij vaak voorkomt in interviews is: "Waarom zijn strings ontworpen als onveranderlijk in Java?"

James Gosling, de maker van Java, werd ooit in een interview gevraagd wanneer je onveranderlijke dingen moet gebruiken, waarop hij antwoordt:

Ik zou een onveranderlijke gebruiken wanneer ik maar kan.

Hij steunt verder zijn argument en stelt functies die onveranderlijkheid biedt, zoals caching, beveiliging, gemakkelijk hergebruik zonder replicatie, enz.

In deze tutorial zullen we verder onderzoeken waarom de Java-taalontwerpers besloten om te behouden Draad onveranderlijk.

2. Wat is een onveranderlijk object?

Een onveranderlijk object is een object waarvan de interne toestand constant blijft nadat deze volledig is gemaakt. Dit betekent dat als het object eenmaal aan een variabele is toegewezen, we de referentie op geen enkele manier kunnen bijwerken of de interne status kunnen muteren.

We hebben een apart artikel dat onveranderlijke objecten in detail bespreekt. Lees het artikel Onveranderlijke objecten in Java voor meer informatie.

3. Waarom is Draad Onveranderlijk in Java?

De belangrijkste voordelen van het onveranderlijk houden van deze klasse zijn caching, beveiliging, synchronisatie en prestaties.

Laten we bespreken hoe deze dingen werken.

3.1. Voorstellen aan Draad Zwembad

De Draad is de meest gebruikte datastructuur. Het Draad literals en ze hergebruiken bespaart veel heap-ruimte omdat ze anders zijn Draad variabelen verwijzen naar hetzelfde object in de Draad zwembad. Draad intern pool dient precies dit doel.

Java String Pool is het speciale geheugengebied waar Snaren worden opgeslagen door de JVM. Sinds Snaren onveranderlijk zijn in Java, optimaliseert de JVM de hoeveelheid geheugen die eraan wordt toegewezen door slechts één kopie van elke letterlijke Draad in het zwembad. Dit proces heet internering:

String s1 = "Hallo wereld"; String s2 = "Hallo wereld"; assertThat (s1 == s2) .isTrue ();

Vanwege de aanwezigheid van de Draad pool in het voorgaande voorbeeld verwijzen twee verschillende variabelen naar hetzelfde Draad object uit de pool, waardoor cruciale geheugenresources worden bespaard.

We hebben een apart artikel gewijd aan Java Draad Zwembad. Ga voor meer informatie naar dat artikel.

3.2. Veiligheid

De Draad wordt veel gebruikt in Java-applicaties om gevoelige stukjes informatie op te slaan, zoals gebruikersnamen, wachtwoorden, verbindings-URL's, netwerkverbindingen, enz. Het wordt ook op grote schaal gebruikt door JVM-klasseladers tijdens het laden van klassen.

Vandaar beveiligen Draad class is cruciaal voor de beveiliging van de hele applicatie in het algemeen. Overweeg bijvoorbeeld dit eenvoudige codefragment:

void criticalMethod (String userName) {// voer beveiligingscontroles uit als (! isAlphaNumeric (userName)) {nieuwe SecurityException (); } // doe een aantal secundaire taken initializeDatabase (); // kritische taak connection.executeUpdate ("UPDATE Klanten SET Status = 'Actief'" + "WHERE Gebruikersnaam = '" + gebruikersnaam + "'"); }

Stel dat we in het bovenstaande codefragment een Draad bezwaar maken van een onbetrouwbare bron. We voeren in eerste instantie alle noodzakelijke beveiligingscontroles uit om te controleren of het Draad is alleen alfanumeriek, gevolgd door nog enkele bewerkingen.

Onthoud dat onze onbetrouwbare source caller-methode hier nog steeds naar verwijst gebruikersnaam voorwerp.

Als Snaren veranderbaar waren, en tegen de tijd dat we de update uitvoeren, kunnen we er niet zeker van zijn dat de Draad we ontvingen, zelfs na het uitvoeren van beveiligingscontroles, veilig zouden zijn. De onbetrouwbare beller-methode heeft nog steeds de referentie en kan de Draad tussen integriteitscontroles. Hierdoor is onze query in dit geval vatbaar voor SQL-injecties. Zo veranderlijk Snaren kan in de loop van de tijd tot een verslechtering van de veiligheid leiden.

Het kan ook gebeuren dat de Draadgebruikersnaam is zichtbaar voor een andere thread, die dan zijn waarde zou kunnen veranderen na de integriteitscontrole.

Over het algemeen komt onveranderlijkheid ons in dit geval te hulp omdat het gemakkelijker is om met gevoelige code te werken wanneer waarden niet veranderen, omdat er minder interleavings van bewerkingen zijn die het resultaat kunnen beïnvloeden.

3.3. Synchronisatie

Onveranderlijk zijn maakt automatisch het Draad thread safe omdat ze niet worden gewijzigd wanneer ze worden geopend vanuit meerdere threads.

Vandaar onveranderlijke objecten kunnen in het algemeen worden gedeeld over meerdere threads die tegelijkertijd worden uitgevoerd. Ze zijn ook draadveilig omdat als een thread de waarde verandert, in plaats van hetzelfde te wijzigen, een nieuw Draad zou worden gemaakt in de Draad zwembad. Vandaar, Snaren zijn veilig voor multi-threading.

3.4. Hashcode caching

Sinds Draad objecten worden overvloedig gebruikt als datastructuur, ze worden ook veel gebruikt in hash-implementaties zoals Hash kaart, HashTable, HashSet, etc. Bij het werken met deze hash-implementaties, hashCode () methode wordt vrij vaak aangeroepen voor bucketing.

De onveranderlijkheid garandeert Snaren dat hun waarde niet verandert. Zo de hashCode () methode wordt overschreven in Draad class om caching te vergemakkelijken, zodat de hash wordt berekend en in de cache wordt opgeslagen tijdens de eerste hashCode () call en dezelfde waarde wordt sindsdien geretourneerd.

Dit verbetert op zijn beurt de prestaties van verzamelingen die hash-implementaties gebruiken wanneer ze worden gebruikt met Draad voorwerpen.

Aan de andere kant, veranderlijk Snaren zou twee verschillende hashcodes produceren op het moment van invoegen en ophalen als de inhoud van Draad is gewijzigd na de bewerking, waardoor mogelijk het waarde-object in de Kaart.

3.5. Prestatie

Zoals we eerder zagen, Draad pool bestaat omdat Snaren zijn onveranderlijk. Het verbetert op zijn beurt de prestaties door heap-geheugen te besparen en snellere toegang tot hash-implementaties bij gebruik met Snaren.

Sinds Draad is de meest gebruikte datastructuur, waardoor de prestaties van Draad hebben een aanzienlijk effect op het verbeteren van de prestaties van de hele applicatie in het algemeen.

4. Conclusie

Via dit artikel kunnen we dat concluderen Strings zijn onveranderlijk, precies zodat hun referenties kunnen worden behandeld als een normale variabele en men ze kan doorgeven, tussen methoden en over threads, zonder zich zorgen te hoeven maken of de feitelijke Draad object waarnaar het verwijst, zal veranderen.

We hebben ook geleerd wat de andere redenen kunnen zijn die de Java taalontwerpers om deze klasse als onveranderlijk te maken.