StringBuffer versus String

Java biedt de StringBufferen Stringklassen, en de Stringklasse wordt gebruikt om tekenreeksen te manipuleren die niet kunnen worden gewijzigd. Simpel gezegd, objecten van het type Stringzijn alleen-lezen en onveranderlijk. De StringBufferklasse wordt gebruikt om tekens weer te geven die kunnen worden gewijzigd.

Het significante prestatieverschil tussen deze twee klassen is dat het StringBuffersneller is dan Stringbij het uitvoeren van eenvoudige aaneenschakelingen. In Stringmanipulatiecode worden tekenreeksen routinematig aaneengeschakeld. Met behulp van de Stringklasse worden aaneenschakelingen doorgaans als volgt uitgevoerd:

String str = new String ("Stanford"); str + = "Verloren !!";

Als u StringBufferdezelfde aaneenschakeling zou gebruiken, heeft u code nodig die er als volgt uitziet:

StringBuffer str = nieuwe StringBuffer ("Stanford"); str.append ("Lost !!");

Ontwikkelaars gaan er meestal van uit dat het eerste voorbeeld hierboven efficiënter is, omdat ze denken dat het tweede voorbeeld, dat de appendmethode voor aaneenschakeling gebruikt, duurder is dan het eerste voorbeeld, dat de +operator gebruikt om twee Stringobjecten samen te voegen .

De +operator lijkt onschuldig, maar de gegenereerde code levert enkele verrassingen op. Het gebruik van a StringBuffervoor aaneenschakeling kan in feite code produceren die aanzienlijk sneller is dan het gebruik van een String. Om te ontdekken waarom dit het geval is, moeten we de gegenereerde bytecode uit onze twee voorbeelden bekijken. De bytecode voor het voorbeeld met Stringziet er als volgt uit:

0 new # 7 3 dup 4 ldc # 2 6 invokespecial # 12 9 astore_1 10 new # 8 13 dup 14 aload_1 15 invokestatic # 23 18 invokespecial # 13 21 ldc # 1 23 invokevirtual # 15 26 invokevirtual # 22 29 astore_1 

De bytecode op locaties 0 t / m 9 wordt uitgevoerd voor de eerste regel code, namelijk:

 String str = new String ("Stanford"); 

Vervolgens wordt de bytecode op locatie 10 t / m 29 uitgevoerd voor de aaneenschakeling:

 str + = "Verloren !!"; 

Het wordt hier interessant. De bytecode die voor de aaneenschakeling wordt gegenereerd, maakt een StringBufferobject aan en roept vervolgens zijn appendmethode aan: het tijdelijke StringBufferobject wordt gemaakt op locatie 10 en de appendmethode wordt aangeroepen op locatie 23. Omdat de Stringklasse onveranderlijk is, StringBuffermoet een worden gebruikt voor aaneenschakeling.

Nadat de aaneenschakeling op het StringBufferobject is uitgevoerd , moet het weer worden geconverteerd naar een String. Dit gebeurt met de aanroep van de toStringmethode op locatie 26. Deze methode maakt Stringvan het tijdelijke StringBufferobject een nieuw object aan . Het maken van dit tijdelijke StringBufferobject en het daarna weer ombouwen tot Stringobject is erg duur.

Samengevat resulteren de twee bovenstaande regels code in de creatie van drie objecten:

  1. Een Stringobject op locatie 0
  2. Een StringBufferobject op locatie 10
  3. Een Stringobject op locatie 26

Laten we nu eens kijken naar de bytecode die voor het voorbeeld is gegenereerd met behulp van StringBuffer:

0 nieuw # 8 3 dup 4 ldc # 2 6 invokespecial # 13 9 astore_1 10 aload_1 11 ldc # 1 13 invokevirtual # 15 16 pop 

De bytecode op locaties 0 t / m 9 wordt uitgevoerd voor de eerste regel code:

 StringBuffer str = nieuwe StringBuffer ("Stanford"); 

De bytecode op locatie 10 tot 16 wordt dan uitgevoerd voor de aaneenschakeling:

 str.append ("Lost !!"); 

Merk op dat, zoals het geval is in het eerste voorbeeld, deze code de appendmethode van een StringBufferobject aanroept . In tegenstelling tot het eerste voorbeeld is het echter niet nodig om een ​​tijdelijke te maken StringBufferen deze vervolgens om te zetten in een Stringobject. Deze code maakt slechts één object, de StringBuffer, op locatie 0.

Concluderend: StringBufferaaneenschakeling is aanzienlijk sneller dan Stringaaneenschakeling. Het is duidelijk dat StringBuffers moeten worden gebruikt bij dit type operatie, indien mogelijk. Als de functionaliteit van de Stringklasse gewenst is, overweeg dan om a te gebruiken StringBuffervoor aaneenschakeling en vervolgens één conversie uit te voeren naar String.

Reggie Hutcherson is een evangelist van Sun-technologie. Hij verkondigt Sun's Java 2 Platform-technologieën over de hele wereld, waarbij hij zich concentreert op J2SE en de HotSpot-prestatie-engine.

Lees meer over dit onderwerp

  • " JavaWorld introduceert nieuwe wekelijkse Java-prestatiekolom", Reggie Hutcherson ( JavaWorld, maart 2000)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf.html

  • "De basisprincipes van Java-prestaties", Reggie Hutcherson ( JavaWorld, maart 2000)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_2.html

  • "Prestatieprobleem of ontwerpprobleem?" Reggie Hutcherson ( JavaWorld, maart 2000)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_3.html

  • "Compiler-optimalisaties", Reggie Hutcherson ( JavaWorld, maart 2000)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_4.html

Dit verhaal, "StringBuffer versus String", is oorspronkelijk gepubliceerd door JavaWorld.