A Java programozási nyelv egyik alapvető és leggyakrabban használt adattípusa a karakterlánc, vagy angolul string. Gyakorlatilag minden alkalmazásban szükség van szöveges adatok kezelésére, legyen szó felhasználói bemenetről, fájltartalomról, adatbázis rekordokról vagy hálózati kommunikációról. A Java stringek nem csupán karakterek egyszerű sorozatai, hanem komplex objektumok, melyek sajátos viselkedéssel és számos beépített metódussal rendelkeznek a szöveges adatok hatékony kezelésére. Ahhoz, hogy a Java fejlesztők igazán robusztus és performáns alkalmazásokat építhessenek, elengedhetetlen a stringek mélyreható megértése: hogyan működnek, milyen tulajdonságaik vannak, és hogyan használhatók optimálisan.
A stringek a szöveges adatok reprezentálására szolgálnak a Java-ban. Bár első pillantásra egyszerűnek tűnnek, számos finomságot rejtenek, melyek megértése kulcsfontosságú a hatékony és hibamentes kód írásához. A Java nyelvben a stringek nem primitív adattípusok, mint az int
vagy a boolean
, hanem objektumok. Ez azt jelenti, hogy az java.lang.String
osztály példányai, és mint ilyenek, metódusokkal, mezőkkel és objektumorientált tulajdonságokkal rendelkeznek.
Mi a Java karakterlánc (string)? Alapvető definíció és jelentősége
A Java karakterlánc, vagy string, egy karakterekből álló, rendezett sorozat. Ezek a karakterek Unicode szabvány szerint vannak kódolva, ami lehetővé teszi a világ bármely nyelvének karaktereinek kezelését. A Java stringek egyedi és talán legfontosabb jellemzője az immutabilitás, azaz a megváltoztathatatlanság. Ez azt jelenti, hogy miután egy string objektum létrejött, a tartalma már nem módosítható.
Az java.lang.String
osztály a Java Standard Library része, és a java.lang
csomagban található, ami azt jelenti, hogy automatikusan importálódik minden Java programba. Ez az osztály biztosítja a stringek kezeléséhez szükséges összes funkcionalitást, beleértve az összefűzést, összehasonlítást, keresést, cserét és formázást. A stringek objektumként való kezelése számos előnnyel jár a primitív tömbökkel szemben, például a beépített metódusok gazdag készletével és a memóriakezelés optimalizálásával.
A stringek alapvető építőkövei a modern alkalmazásoknak. Gondoljunk csak a felhasználónevekre, jelszavakra, e-mail címekre, fájlnevekre, URL-ekre, vagy akár a program forráskódjában lévő literálokra. Mindezek stringek formájában jelennek meg és kerülnek feldolgozásra. A stringek hatékony és biztonságos kezelése elengedhetetlen a program stabilitása és megbízhatósága szempontjából.
A Java stringek nem csupán szöveges adatok tárolására szolgálnak, hanem a programozás számos területén kulcsfontosságú szerepet töltenek be, az adatok beolvasásától a kimeneti megjelenítésig.
A Java string immutabilitása: Miért fontos és mit jelent?
Az immutabilitás (megváltoztathatatlanság) a Java stringek egyik legfontosabb tulajdonsága. Ez azt jelenti, hogy miután egy String
objektum létrejött, a tartalma nem módosítható. Ha úgy tűnik, hogy egy stringet módosítunk (például összefűzünk két stringet), valójában egy teljesen új string objektum jön létre a módosított tartalommal, és a változó referenciája átáll az új objektumra, míg az eredeti string változatlan marad.
Ez a tulajdonság számos előnnyel jár, melyek közül a legfontosabbak a következők:
- Szálbiztonság (Thread Safety): Mivel a stringek megváltoztathatatlanok, több szál is biztonságosan hozzáférhet ugyanahhoz a string objektumhoz anélkül, hogy aggódni kellene az adatsérülés miatt. Nincs szükség szinkronizációra, ami javítja a teljesítményt és egyszerűsíti a párhuzamos programozást.
- Biztonság: Az immutabilitás kulcsfontosságú a biztonság szempontjából, különösen olyan érzékeny adatok, mint például a jelszavak vagy fájlnevek kezelésekor. Ha egy stringet átadunk egy metódusnak, biztosak lehetünk benne, hogy a metódus nem fogja módosítani az eredeti string tartalmát. Ez megelőzheti a biztonsági réseket, mint például az SQL injekciót vagy a fájlútvonal manipulációt.
- Hash kód caching: A stringek
hashCode()
metódusa gyakran használatos hash alapú adatszerkezetekben, mint például aHashMap
vagy aHashSet
. Mivel a stringek megváltoztathatatlanok, a hash kódjukat egyszer kiszámolhatjuk és elmenthetjük (cache-elhetjük), így nem kell újra és újra kiszámolni minden alkalommal, amikor szükség van rá. Ez jelentős teljesítménynövekedést eredményezhet. - String Pool használata: Az immutabilitás teszi lehetővé a String Constant Pool létezését, ami egy speciális memóriaterület a JVM-ben, ahol a gyakran használt string literálok tárolódnak. Ez memóriaoptimalizációt eredményez, mivel több string referencia is mutathat ugyanarra az objektumra a poolban, ahelyett, hogy minden egyes string literálhoz új objektum jönne létre.
Az immutabilitás azonban néha hátránnyal is járhat, különösen akkor, ha sok string manipulációs műveletet kell végrehajtani. Minden egyes módosítás (pl. összefűzés) egy új string objektum létrehozását jelenti, ami memóriapazarláshoz és teljesítményromláshoz vezethet, ha nem megfelelően kezelik. Ilyen esetekben a StringBuilder
vagy StringBuffer
osztályok használata ajánlott.
Stringek létrehozása és inicializálása
A Java-ban két fő módon hozhatunk létre string objektumokat:
String literálok használata
Ez a leggyakoribb és leginkább ajánlott módja a stringek létrehozásának. Egy string literál egy sor karakter, amelyet dupla idézőjelek közé zárunk. Amikor a Java virtuális gép (JVM) egy string literállal találkozik, először megnézi a String Constant Poolban, hogy létezik-e már az adott tartalommal rendelkező string. Ha igen, akkor az existing objektumra mutató referenciát adja vissza. Ha nem, akkor létrehoz egy új string objektumot a poolban, és arra ad vissza referenciát.
String nev = "Példa Béla";
String uzenet = "Üdvözlünk!";
String uzenet2 = "Üdvözlünk!"; // Ez ugyanarra az objektumra fog mutatni, mint az 'uzenet'
Ez a mechanizmus a String Pool nevű memóriaterületnek köszönhető, ami optimalizálja a memóriahasználatot, mivel elkerüli a duplikált string objektumok létrehozását az azonos tartalmú literálok esetében.
A new
kulcsszóval történő létrehozás
A stringek objektumok, így a new
kulcsszóval is létrehozhatók, akárcsak bármely más objektum. Ebben az esetben a JVM mindig egy új string objektumot hoz létre a heap memóriában, függetlenül attól, hogy létezik-e már azonos tartalmú string a String Poolban vagy máshol a heap-en.
String nevObjektum = new String("Példa Béla");
String uzenetObjektum = new String("Üdvözlünk!"); // Mindig új objektum jön létre
Fontos különbség, hogy ha két stringet hozunk létre a new
kulcsszóval, még ha tartalmuk megegyezik is, azok két különböző objektumként fognak létezni a memóriában. Ezzel szemben a literálok azonos tartalom esetén ugyanarra az objektumra mutathatnak.
Általánosságban elmondható, hogy a string literálok használata preferált, mivel azok optimalizáltak a memória szempontjából a String Pool révén. A new String()
konstruktor használata csak akkor indokolt, ha kifejezetten új objektumot szeretnénk létrehozni, például bájttömbökből vagy karaktertömbökből, vagy ha szándékosan el akarjuk kerülni a String Poolot valamilyen speciális okból (ami ritkán fordul elő a gyakorlatban).
A String Constant Pool részletesebben

A String Constant Pool (gyakran csak String Pool) egy speciális memóriaterület a Java virtuális gép (JVM) heap-jében, ahol a string literálok tárolódnak. Ennek a poolnak az elsődleges célja a memória optimalizálása és a stringek kezelésének hatékonyabbá tétele.
Amikor a Java kód fordításra kerül, a fordító az összes string literált a String Poolba helyezi. Futásidőben, amikor a JVM egy string literállal találkozik:
- Megvizsgálja a String Poolt, hogy létezik-e már olyan string objektum, amelynek tartalma megegyezik a literál tartalmával.
- Ha igen, akkor a JVM egyszerűen visszaadja a már létező objektumra mutató referenciát.
- Ha nem, akkor a JVM létrehoz egy új string objektumot a String Poolban, és visszaadja annak referenciáját.
Ez a mechanizmus biztosítja, hogy az azonos tartalmú string literálok csak egyszer létezzenek a memóriában, ezzel csökkentve a memóriaigényt. Ez különösen hasznos olyan alkalmazásokban, ahol sok azonos string literál fordul elő.
A new String("valami")
használata azonban kikerüli ezt az optimalizációt. Amikor a new String()
konstruktort hívjuk meg, a JVM mindig létrehoz egy új string objektumot a heap-en, akkor is, ha azonos tartalmú string már létezik a String Poolban. Sőt, ha a konstruktor argumentuma egy string literál, akkor az is bekerül a poolba, így valójában két string objektum jön létre: egy a poolban (a literálhoz) és egy a heap-en (a new
operátor miatt).
Az intern()
metódus
A String
osztály rendelkezik egy intern()
metódussal, amely lehetővé teszi, hogy egy heap-en létrehozott stringet beillesszünk a String Poolba, vagy lekérdezzük annak poolbeli megfelelőjét. Amikor az intern()
metódust meghívjuk egy string objektumon:
- A JVM ellenőrzi, hogy a string tartalma már létezik-e a String Poolban.
- Ha igen, akkor visszaadja a poolban lévő string objektum referenciáját.
- Ha nem, akkor hozzáadja az aktuális string objektumot a poolhoz, és visszaadja annak referenciáját.
String s1 = new String("hello"); // s1 a heap-en van
String s2 = "hello"; // s2 a String Poolban van
String s3 = s1.intern(); // s3 most már ugyanarra az objektumra mutat, mint s2
System.out.println(s1 == s2); // false (különböző objektumok)
System.out.println(s2 == s3); // true (ugyanaz az objektum a poolban)
Az intern()
metódus használata néha javíthatja a teljesítményt, különösen, ha sok stringet hasonlítunk össze ==
operátorral, miután azokat „interneltük”. Azonban óvatosan kell használni, mivel a String Pool mérete korlátozott, és túl sok string internelése memóriaproblémákhoz vezethet.
Alapvető string műveletek és metódusok
A String
osztály számos beépített metódust kínál a stringek manipulálására és lekérdezésére. Ezek a metódusok a string immutabilitása miatt mindig új string objektumot adnak vissza, ha módosítást végeznek, az eredeti stringet érintetlenül hagyva.
Hossz meghatározása: length()
A length()
metódus visszaadja a stringben lévő karakterek számát. Ez egy egyszerű, de rendkívül gyakran használt metódus.
String s = "Hello Világ!";
int hossz = s.length(); // hossz értéke: 12
Karakterek elérése: charAt()
A charAt(int index)
metódus visszaadja a string adott pozícióján lévő karaktert. Fontos megjegyezni, hogy az indexelés 0-tól indul, tehát az első karakter indexe 0, a másodiké 1, és így tovább.
String s = "Java";
char elsoKarakter = s.charAt(0); // 'J'
char utolsoKarakter = s.charAt(s.length() - 1); // 'a'
// char hibasKarakter = s.charAt(4); // StringIndexOutOfBoundsException
Stringek összefűzése (konkatenáció)
A stringek összefűzésére több módszer is létezik:
+
operátor: Ez a leggyakoribb és legintuitívabb módja a stringek összefűzésének. A Java fordító intelligensen kezeli ezt az operátort, és a háttérben gyakranStringBuilder
-t használ az optimalizálás érdekében, különösen több összefűzés esetén.concat()
metódus: Ez a metódus egy másik stringet fűz hozzá az aktuális string végéhez.
String elso = "Hello";
String masodik = "Világ";
String osszefuzott1 = elso + " " + masodik + "!"; // "Hello Világ!"
String osszefuzott2 = elso.concat(" ").concat(masodik).concat("!"); // "Hello Világ!"
Bár a +
operátor kényelmes, intenzív és gyakori összefűzési műveletek esetén (például egy ciklusban) a StringBuilder
használata sokkal hatékonyabb, mivel az nem hoz létre minden lépésben új string objektumot.
Részstringek kivágása: substring()
A substring()
metódusok lehetővé teszik a string egy részének kivágását:
substring(int beginIndex)
: Visszaadja a string egy részét abeginIndex
-től a string végéig.substring(int beginIndex, int endIndex)
: Visszaadja a string egy részét abeginIndex
-től (beleértve) azendIndex
-ig (nem beleértve).
String mondat = "Java programozás";
String szo1 = mondat.substring(0, 4); // "Java"
String szo2 = mondat.substring(5, 16); // "programozás"
String szo3 = mondat.substring(5); // "programozás"
Stringek összehasonlítása és keresése
A stringek összehasonlítása és bennük történő keresés a mindennapi programozás során gyakori feladat. Fontos megérteni a különböző metódusok működését és a köztük lévő különbségeket.
equals()
vs. ==
Ez az egyik leggyakoribb hibaforrás a Java stringekkel kapcsolatban.
- A
==
operátor két objektum referenciáját hasonlítja össze. Azt ellenőrzi, hogy a két referencia ugyanarra az objektumra mutat-e a memóriában. - Az
equals()
metódus két string objektum tartalmát hasonlítja össze. Azt ellenőrzi, hogy a két string karakterről karakterre megegyezik-e.
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true (mindkettő a String Poolban lévő "hello"-ra mutat)
System.out.println(s1 == s3); // false (s1 a poolban, s3 a heap-en van)
System.out.println(s1.equals(s2)); // true (tartalmuk megegyezik)
System.out.println(s1.equals(s3)); // true (tartalmuk megegyezik)
Mindig az equals()
metódust használjuk stringek tartalmának összehasonlítására, kivéve, ha kifejezetten azt akarjuk ellenőrizni, hogy két referencia ugyanarra az objektumra mutat-e.
equalsIgnoreCase()
Ez a metódus hasonló az equals()
-hoz, de figyelmen kívül hagyja a kis- és nagybetűk közötti különbségeket az összehasonlítás során.
String nev1 = "Példa Béla";
String nev2 = "példa béla";
System.out.println(nev1.equals(nev2)); // false
System.out.println(nev1.equalsIgnoreCase(nev2)); // true
startsWith()
, endsWith()
, contains()
Ezek a metódusok a stringek egy adott prefixszel, szuffixszel vagy részstringgel való egyezését ellenőrzik.
startsWith(String prefix)
: Igaz, ha a string a megadott prefixszel kezdődik.endsWith(String suffix)
: Igaz, ha a string a megadott szuffixszel végződik.contains(CharSequence s)
: Igaz, ha a string tartalmazza a megadott karakterláncot.
String fajlNev = "dokumentum.txt";
System.out.println(fajlNev.startsWith("dok")); // true
System.out.println(fajlNev.endsWith(".pdf")); // false
System.out.println(fajlNev.contains("umen")); // true
indexOf()
, lastIndexOf()
Ezek a metódusok egy adott karakter vagy részstring első vagy utolsó előfordulásának indexét adják vissza. Ha a keresett elem nem található, -1
-et adnak vissza.
indexOf(int ch)
/indexOf(String str)
: Az első előfordulás indexe.lastIndexOf(int ch)
/lastIndexOf(String str)
: Az utolsó előfordulás indexe.- Léteznek túlterhelt verziók, amelyek egy adott indexről kezdik a keresést.
String szoveg = "almafa alma alma";
System.out.println(szoveg.indexOf("alma")); // 0
System.out.println(szoveg.lastIndexOf("alma")); // 10
System.out.println(szoveg.indexOf("körte")); // -1
System.out.println(szoveg.indexOf('a')); // 0
System.out.println(szoveg.lastIndexOf('a')); // 14
compareTo()
A compareTo(String anotherString)
metódus lexikografikusan (szótári sorrendben) hasonlít össze két stringet. Visszatérési értéke:
0
, ha a két string azonos.- Negatív szám, ha az aktuális string lexikografikusan megelőzi a paraméterként átadott stringet.
- Pozitív szám, ha az aktuális string lexikografikusan követi a paraméterként átadott stringet.
String s1 = "apple";
String s2 = "banana";
String s3 = "apple";
System.out.println(s1.compareTo(s2)); // Negatív szám (pl. -1)
System.out.println(s2.compareTo(s1)); // Pozitív szám (pl. 1)
System.out.println(s1.compareTo(s3)); // 0
Stringek módosítása és manipulációja
Bár a stringek immutábilisek, a String
osztály számos metódust kínál, amelyek a string tartalmán alapuló új string objektumokat hoznak létre. Ezek a metódusok lehetővé teszik a karakterek cseréjét, szóközök eltávolítását, kis- és nagybetűs átalakítást, valamint a stringek felosztását.
Karakterek cseréje: replace()
, replaceAll()
, replaceFirst()
replace(char oldChar, char newChar)
: Az összes előfordulását lecseréli egy adott karakternek egy másik karakterre.replace(CharSequence target, CharSequence replacement)
: Az összes előfordulását lecseréli egy adott karakterláncnak egy másik karakterláncra.replaceAll(String regex, String replacement)
: Reguláris kifejezés (regex) alapján cseréli le az összes egyező alstringet.replaceFirst(String regex, String replacement)
: Reguláris kifejezés (regex) alapján cseréli le az első egyező alstringet.
String szoveg = "almafa alma";
String cserelt1 = szoveg.replace('a', 'e'); // "elmefe elme"
String cserelt2 = szoveg.replace("alma", "körte"); // "körtefa körte"
String cserelt3 = szoveg.replaceAll("a", "X"); // "XlmXfX XlmX"
String cserelt4 = szoveg.replaceFirst("alma", "körte"); // "körtefa alma"
Szóközök eltávolítása: trim()
, strip()
, stripLeading()
, stripTrailing()
trim()
: Eltávolítja az elején és végén lévő szóközöket (whitespace karaktereket, melyek Unicode értéke U+0020-nál kisebb vagy azzal egyenlő).strip()
(Java 11+): Hasonló atrim()
-hez, de a Unicode whitespace karaktereket is figyelembe veszi.stripLeading()
(Java 11+): Csak az elején lévő szóközöket távolítja el.stripTrailing()
(Java 11+): Csak a végén lévő szóközöket távolítja el.
String szovegSzokozzel = " Hello Világ! ";
System.out.println("'" + szovegSzokozzel.trim() + "'"); // 'Hello Világ!'
System.out.println("'" + szovegSzokozzel.strip() + "'"); // 'Hello Világ!'
System.out.println("'" + szovegSzokozzel.stripLeading() + "'"); // 'Hello Világ! '
System.out.println("'" + szovegSzokozzel.stripTrailing() + "'");// ' Hello Világ!'
Kis- és nagybetűs átalakítás: toUpperCase()
, toLowerCase()
Ezek a metódusok a string összes karakterét nagybetűssé vagy kisbetűssé alakítják.
String s = "Hello Világ!";
String nagybetus = s.toUpperCase(); // "HELLO VILÁG!"
String kisbetus = s.toLowerCase(); // "hello világ!"
Stringek felosztása: split()
A split(String regex)
metódus egy stringet egy reguláris kifejezés (elválasztó) alapján darabokra oszt, és egy string tömböt ad vissza.
String lista = "alma,körte,szilva";
String[] gyumolcsok = lista.split(","); // {"alma", "körte", "szilva"}
String mondat = "Ez egy példa mondat.";
String[] szavak = mondat.split(" "); // {"Ez", "egy", "példa", "mondat."}
Stringek összefűzése join()
metódussal (Java 8+)
A Java 8-tól kezdődően a String.join()
statikus metódus leegyszerűsíti a stringek összefűzését egy elválasztó karakterlánc segítségével.
String[] nevek = {"Anna", "Béla", "Cecília"};
String osszefuzottNevek = String.join(", ", nevek); // "Anna, Béla, Cecília"
List<String> elemek = Arrays.asList("egy", "kettő", "három");
String osszefuzottElemek = String.join("-", elemek); // "egy-kettő-három"
StringBuilder
és StringBuffer
: Mikor és miért használjuk őket?
Ahogy korábban említettük, a String
objektumok immutábilisek, ami azt jelenti, hogy minden módosítás (pl. összefűzés) egy új string objektum létrehozását eredményezi. Ez rendben van, ha ritkán kell stringeket módosítani. Azonban, ha egy stringet gyakran kell manipulálni, például egy ciklusban, akkor a sok ideiglenes string objektum létrehozása memória pazarláshoz és jelentős teljesítményromláshoz vezethet.
Ilyen esetekben lépnek színre a StringBuilder
és StringBuffer
osztályok. Ezek az osztályok mutábilis (módosítható) karakterláncokat reprezentálnak, azaz lehetővé teszik a string tartalmának közvetlen módosítását anélkül, hogy minden egyes műveletnél új objektumot kellene létrehozni.
StringBuilder
A StringBuilder
egy nem szinkronizált, mutábilis karakterlánc. Ez azt jelenti, hogy nem szálbiztos, de cserébe gyorsabb, mint a StringBuffer
. Ideális választás, ha string manipulációt egyetlen szálon belül végzünk.
StringBuilder sb = new StringBuilder("Start");
sb.append(" programozás"); // "Start programozás"
sb.insert(5, "Java "); // "Start Java programozás"
sb.delete(0, 5); // "Java programozás"
sb.reverse(); // "sázozmargorp avaJ"
String eredmeny = sb.toString(); // Visszaalakítás String objektummá
StringBuffer
A StringBuffer
hasonló a StringBuilder
-hez, de szinkronizált. Ez azt jelenti, hogy szálbiztos, azaz több szál is biztonságosan használhatja ugyanazt a StringBuffer
objektumot anélkül, hogy adatsérülés történne. A szinkronizáció ára azonban a lassabb teljesítmény.
A metódusai megegyeznek a StringBuilder
metódusaival (append()
, insert()
, delete()
, reverse()
stb.).
StringBuffer sbuf = new StringBuffer("Adatok");
sbuf.append(" feldolgozása");
// ... további műveletek
String eredmeny = sbuf.toString();
Mikor melyiket használjuk?
StringBuilder
: Használjuk, ha a string manipuláció egyetlen szálon belül történik, és a teljesítmény kritikus. Ez a leggyakoribb forgatókönyv.StringBuffer
: Használjuk, ha a string manipuláció több szál között megosztott objektumon történik, és a szálbiztonság elengedhetetlen. A modern Java alkalmazásokban ajava.util.concurrent
csomag fejlettebb szinkronizációs mechanizmusokat kínál, így aStringBuffer
használata ritkábbá vált, de továbbra is érvényes opció.String
: Használjuk az alapértelmezett string reprezentációhoz, ha a string tartalma ritkán vagy egyáltalán nem változik.
A
String
immutabilitása biztonságot és szálbiztonságot nyújt, de teljesítményproblémákat okozhat intenzív manipuláció esetén. Ilyenkor aStringBuilder
vagyStringBuffer
használata elengedhetetlen a hatékonyság megőrzéséhez.
Stringek és más adattípusok közötti konverzió
A stringek gyakran interakcióba lépnek más adattípusokkal. Fontos tudni, hogyan lehet konvertálni stringek és számok, karaktertömbök vagy bájttömbök között.
Számok stringgé alakítása
String.valueOf()
: Ez egy statikus metódus, amely bármely primitív típust (int
,double
,boolean
stb.) vagy objektumot stringgé alakít. Ez az ajánlott módszer, mivel null-biztos és sokoldalú.Integer.toString()
,Double.toString()
stb.: A primitív típusok wrapper osztályai is biztosítanaktoString()
metódusokat.- Üres string összefűzése: Egy számhoz üres stringet fűzve is stringet kapunk (pl.
"" + 123
), de ez kevésbé explicit és potenciálisan lassabb.
int szam = 123;
double lebegopontos = 45.67;
boolean logikai = true;
String s1 = String.valueOf(szam); // "123"
String s2 = Integer.toString(szam); // "123"
String s3 = String.valueOf(lebegopontos); // "45.67"
String s4 = String.valueOf(logikai); // "true"
Stringek számokká alakítása
Integer.parseInt()
,Double.parseDouble()
stb.: Ezek a statikus metódusok stringeket alakítanak át a megfelelő primitív számtípusokká. Ha a string nem érvényes számot tartalmaz,NumberFormatException
-t dobnak.
String szamString = "123";
String lebegopontosString = "45.67";
int i = Integer.parseInt(szamString); // 123
double d = Double.parseDouble(lebegopontosString); // 45.67
// int hiba = Integer.parseInt("abc"); // NumberFormatException
Karaktertömbök és stringek
toCharArray()
: AString
osztálytoCharArray()
metódusa visszaadja a string karaktertömb reprezentációját.- String konstruktorok: A
String
osztály számos konstruktora elfogad karaktertömböt, lehetővé téve a string létrehozását belőlük.
String s = "Hello";
char[] charArray = s.toCharArray(); // {'H', 'e', 'l', 'l', 'o'}
char[] masikCharArray = {'J', 'a', 'v', 'a'};
String sMasik = new String(masikCharArray); // "Java"
Érdemes megjegyezni, hogy érzékeny adatok, mint például jelszavak tárolására és kezelésére gyakran a char[]
tömbök használata javasolt a String
helyett. Ennek oka, hogy a char[]
tartalmát a használat után felülírhatjuk (nullázhatjuk), így az nem marad sokáig a memóriában, ellentétben az immutábilis stringekkel, amelyek garbage collection-ig élnek, és így potenciálisan hozzáférhetővé válnak a memóriadumpokból.
Bájttömbök és stringek
A stringek és bájttömbök közötti konverzió különösen fontos I/O (input/output) műveletek során, például fájlok olvasása vagy hálózati kommunikáció esetén. A karakterek bájtokká alakításához egy karakterkódolásra (pl. UTF-8, ISO-8859-1) van szükség.
getBytes()
: AString
osztálygetBytes()
metódusa stringet alakít át bájttömbökké. Használható paraméter nélkül (az alapértelmezett kódolást használja), vagy egyCharset
objektummal vagy kódolás nevével.- String konstruktorok: A
String
osztály konstruktorai bájttömböket is elfogadnak, szintén választható karakterkódolással.
String s = "Hello Világ!";
byte[] utf8Bytes = s.getBytes(StandardCharsets.UTF_8);
String visszaalakitva = new String(utf8Bytes, StandardCharsets.UTF_8); // "Hello Világ!"
String formázás Java-ban
A string formázás lehetővé teszi, hogy dinamikusan hozzunk létre stringeket, beillesztve változókat vagy kifejezéseket egy előre definiált sablonba. A Java több módszert is kínál erre.
String.format()
és System.out.printf()
A String.format()
statikus metódus és a System.out.printf()
metódus (ami a C nyelv printf
függvényéhez hasonló) rendkívül rugalmas string formázást tesz lehetővé formátum specifikátorok használatával.
Formátum specifikátor | Leírás | Példa |
---|---|---|
%s |
String | String.format("Név: %s", "János") |
%d |
Egész szám (decimális) | String.format("Kor: %d", 30) |
%f |
Lebegőpontos szám | String.format("Ár: %.2f", 123.456) (két tizedesjegy) |
%c |
Karakter | String.format("Betű: %c", 'A') |
%b |
Logikai érték | String.format("Aktív: %b", true) |
%t |
Dátum és idő | String.format("Dátum: %tD", new Date()) |
String nev = "Anna";
int kor = 25;
double egyenleg = 1500.75;
// String.format()
String uzenet = String.format("A felhasználó neve %s, kora %d, egyenlege %.2f Ft.", nev, kor, egyenleg);
System.out.println(uzenet); // "A felhasználó neve Anna, kora 25, egyenlege 1500.75 Ft."
// System.out.printf()
System.out.printf("Üdvözlünk, %s! Az aktuális idő: %tH:%tM:%tS%n", nev, new Date(), new Date(), new Date());
// "Üdvözlünk, Anna! Az aktuális idő: 10:30:45" (például)
A formátum specifikátorok széles skáláját kínálják a formázási lehetőségeknek, beleértve a szélességet, precizitást, igazítást és speciális zászlókat.
MessageFormat
A java.text.MessageFormat
osztályt akkor érdemes használni, ha a string formázása lokalizációt (nyelvi különbségeket) is figyelembe vesz, vagy ha összetettebb sablonokra van szükség, ahol a paraméterek sorrendje változhat a nyelvtől függően.
String minta = "Hello {0}! Ma {1} van, és {2} fok van.";
String eredmeny = MessageFormat.format(minta, "János", "hétfő", 20);
System.out.println(eredmeny); // "Hello János! Ma hétfő van, és 20 fok van."
Reguláris kifejezések (Regex) a Java stringkezelésben
A reguláris kifejezések (regex) rendkívül erőteljes eszközök a szöveges adatok keresésére, cseréjére és validálására. A Java beépített támogatást nyújt a regexekhez a java.util.regex
csomagban található Pattern
és Matcher
osztályokon keresztül.
Egy reguláris kifejezés egy mintát definiál, amelyet a szövegben keresünk. Ezek a minták speciális karaktereket és metakaraktereket tartalmazhatnak, amelyek rugalmas keresést tesznek lehetővé.
Pattern
és Matcher
osztályok
Pattern
: Ez az osztály egy reguláris kifejezés fordított reprezentációját képviseli. APattern.compile()
statikus metódussal hozhatunk létrePattern
objektumot egy stringből.Matcher
: Ez az osztály egyPattern
objektumot és egy bemeneti karakterláncot vesz alapul, és végrehajtja a keresési műveleteket. APattern
objektummatcher()
metódusával hozhatunk létreMatcher
objektumot.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String szoveg = "A kód 12345 és 67890 számokat tartalmaz.";
String regex = "\\d+"; // Keresünk egy vagy több számjegyet
Pattern minta = Pattern.compile(regex);
Matcher illeszto = minta.matcher(szoveg);
while (illeszto.find()) {
System.out.println("Találat: " + illeszto.group());
}
// Kimenet:
// Találat: 12345
// Találat: 67890
Gyakori regex műveletek
- Keresés (
find()
): Megtalálja a következő egyezést a bemeneti stringben. - Cserélés (
replaceAll()
,replaceFirst()
): AString
osztályreplaceAll()
ésreplaceFirst()
metódusai is reguláris kifejezéseket használnak. AMatcher
osztályreplaceAll()
ésreplaceFirst()
metódusai is elérhetők. - Validálás (
matches()
): AString
osztálymatches(String regex)
metódusa ellenőrzi, hogy a teljes string egyezik-e a megadott reguláris kifejezéssel.
// Validálás
String email = "pelda@example.com";
boolean isValidEmail = email.matches("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$");
System.out.println("Érvényes e-mail: " + isValidEmail); // true
// Cserélés
String datum = "2023-10-26";
String atalakitottDatum = datum.replaceAll("-", "/"); // "2023/10/26"
A reguláris kifejezések elsajátítása jelentősen növeli a stringkezelési képességeket, de komplexitásuk miatt gyakorlást igényelnek.
Teljesítményoptimalizálás és bevált gyakorlatok a Java stringek használatában

A stringek helytelen használata könnyen vezethet teljesítményproblémákhoz és memóriaszivárgáshoz. Néhány bevált gyakorlat és optimalizációs tipp:
- Preferáljuk a string literálokat: Amikor csak lehetséges, használjunk string literálokat (
"hello"
) anew String("hello")
helyett. Ez kihasználja a String Constant Pool előnyeit, és csökkenti a memóriahasználatot. - Használjunk
StringBuilder
-t (vagyStringBuffer
-t) gyakori string módosításokhoz: Ha egy stringet egy ciklusban vagy sokszor kell összefűzni, módosítani, akkor aStringBuilder
(egy szálon) vagyStringBuffer
(több szálon) használata elengedhetetlen a teljesítmény megőrzéséhez. - Ne használjunk
+
operátort ciklusban: Bár a fordító optimalizálhatja a+
operátortStringBuilder
-re, ez nem mindig garantált, és bizonyos esetekben (különösen régebbi Java verzióknál vagy komplex kifejezéseknél) teljesítményromláshoz vezethet. Mindig expliciten használjuk aStringBuilder
-t ciklusokban. - Hatékony string összehasonlítás: Mindig az
equals()
metódust használjuk stringek tartalmának összehasonlítására. Ha a kis- és nagybetűk közötti különbségek nem számítanak, használjuk azequalsIgnoreCase()
metódust. Ha a stringek null értékűek is lehetnek, ellenőrizzük a null értéket, mielőtt metódust hívunk rajtuk, vagy használjunkObjects.equals()
-t (Java 7+). - String pool kihasználása az
intern()
metódussal (óvatosan): Azintern()
metódus használata akkor lehet hasznos, ha nagyszámú, azonos tartalmú stringet kell kezelni, és azok memóriafogyasztását optimalizálni szeretnénk, vagy ha a==
operátorral történő összehasonlítást szeretnénk használni. Azonban túlzott használata a String Pool túlterheléséhez vezethet. - Vigyázzunk a
substring()
-gel (régebbi Java verziókban): A Java 7-es verzió előtt asubstring()
metódus egy új stringet hozott létre, de az eredeti string belső karaktertömbjére mutatott. Ez memóriaszivárgáshoz vezethetett, ha egy nagyon hosszú stringből vágtunk ki egy rövid részletet, mert az eredeti, hosszú string belső tömbje nem szabadult fel, amíg a rövid részstring is élt. A Java 7u6-tól kezdve ez a probléma megoldódott, asubstring()
mindig új belső karaktertömböt hoz létre. - Használjunk megfelelő karakterkódolást: Amikor stringek és bájttömbök között konvertálunk, mindig adjuk meg a karakterkódolást (pl.
StandardCharsets.UTF_8
), hogy elkerüljük az adatsérülést és a platformfüggő viselkedést.
Biztonsági megfontolások a Java stringekkel
A stringek a programok bemeneti és kimeneti adatainak alapvető elemei, ezért biztonsági szempontból is kiemelt figyelmet igényelnek.
- SQL injekció és XSS támadások elkerülése: Ha felhasználói bemenetet használunk adatbázis lekérdezések vagy HTML kimenet generálásához, mindig végezzünk megfelelő validálást és szanálást (escaping). Paraméterezett lekérdezéseket (PreparedStatement) használjunk SQL-hez, és HTML entitásokká alakítsuk a speciális karaktereket HTML kimenet esetén. A stringek immutabilitása itt segít, mert a szanált string egy új objektum lesz, az eredeti, potenciálisan veszélyes string érintetlen marad.
- Érzékeny adatok (jelszavak) kezelése: Jelszavak és más rendkívül érzékeny adatok tárolására és kezelésére ne használjunk
String
objektumot. Helyettechar[]
tömböt alkalmazzunk. Ennek oka, hogy aString
objektumok immutábilisek, és a garbage collector dönti el, mikor szabadítja fel őket. Ez azt jelenti, hogy a jelszó sokáig a memóriában maradhat, és memóriadumpokból kinyerhető. Achar[]
tartalmát viszont a használat után azonnal felülírhatjuk (pl. nullázhatjuk), minimalizálva az expozíciót. - Immutabilitás szerepe a biztonságban: A stringek immutabilitása alapvető biztonsági előnyt jelent. Ha egy stringet átadunk egy metódusnak, biztosak lehetünk benne, hogy a metódus nem fogja módosítani az eredeti string tartalmát. Ez megakadályozza a jogosulatlan adatmódosítást és a biztonsági réseket.
- Fájlútvonalak és URL-ek: Mindig ellenőrizzük és szanáljuk a felhasználói által megadott fájlútvonalakat és URL-eket, hogy elkerüljük a könyvtár bejárási támadásokat vagy rosszindulatú hivatkozásokat.
Újítások a Java stringek világában (Java 8 és újabb verziók)
A Java folyamatosan fejlődik, és az újabb verziók számos hasznos kiegészítést hoztak a String
osztályhoz is, megkönnyítve a fejlesztők munkáját.
Java 8: String.join()
és chars()
String.join(CharSequence delimiter, CharSequence... elements)
: Ahogy már korábban említettük, ez a statikus metódus leegyszerűsíti a stringek összefűzését egy elválasztóval.chars()
: Ez a metódus egyIntStream
-et ad vissza, amely a stringben lévő karakterek Unicode értékét tartalmazza. Ez lehetővé teszi a stringek Stream API-val való hatékony feldolgozását, például szűrést, térképezést vagy redukciót.
String s = "Hello";
s.chars()
.mapToObj(c -> (char) c)
.forEach(System.out::print); // Hello
Java 11: isBlank()
, strip()
, stripLeading()
, stripTrailing()
, repeat()
isBlank()
: Ez a metódus akkor ad visszatrue
értéket, ha a string üres, vagy csak whitespace karaktereket tartalmaz (beleértve a Unicode whitespace-eket is). Ez különbözik azisEmpty()
metódustól, ami csak akkor ad visszatrue
-t, ha a string hossza nulla.strip()
: Hasonló atrim()
metódushoz, de a Unicode whitespace karaktereket is figyelembe veszi, így pontosabb a szóközök eltávolításában.stripLeading()
: Eltávolítja a string elején lévő Unicode whitespace karaktereket.stripTrailing()
: Eltávolítja a string végén lévő Unicode whitespace karaktereket.repeat(int count)
: Ez a metódus a stringet annyiszor ismétli meg, ahányszor acount
paraméter megadja, és az eredményt egy új stringként adja vissza.
String ures = " ";
System.out.println(ures.isEmpty()); // false
System.out.println(ures.isBlank()); // true
String s = "abc";
String ismetles = s.repeat(3); // "abcabcabc"
Ezek az új metódusok egyszerűsítik a stringkezelési feladatokat, és modernizálják a Java string API-ját.
Gyakori hibák és buktatók elkerülése
A stringek használatakor számos gyakori hiba fordulhat elő, amelyek megértésével elkerülhetőek a kellemetlen meglepetések.
equals()
helyett==
használata: Ez a leggyakoribb és legveszélyesebb hiba. A==
operátor objektumreferenciákat hasonlít össze, nem pedig a stringek tartalmát. Mindig azequals()
metódust használjuk a tartalom összehasonlítására.- Null pointer kivételek: Ha egy string referencia
null
értékű, és megpróbálunk metódust hívni rajta (pl.myString.length()
),NullPointerException
fog dobódni. Mindig ellenőrizzük a stringek null értékét, mielőtt metódust hívunk rajtuk, vagy használjunk null-biztos metódusokat/segítőket (pl.Objects.equals()
). - Index out of bounds hibák: A
charAt()
,substring()
és hasonló metódusok indexeket várnak. Ha az átadott index érvénytelen (negatív, vagy nagyobb, mint a string hossza mínusz egy),StringIndexOutOfBoundsException
fog dobódni. Mindig győződjünk meg róla, hogy az indexek érvényesek. - Memóriaszivárgás String poolal (ritkán, de előfordulhat): Bár a String Pool optimalizálja a memóriát, ha túl sok egyedi stringet internelünk, az túlterhelheti a poolt, és memóriaproblémákhoz vezethet, mivel a poolban lévő stringek nem kerülnek garbage collection alá.
- Nem megfelelő karakterkódolás: Amikor stringeket bájttömbökké alakítunk, vagy fordítva, a nem megfelelő karakterkódolás használata adatvesztéshez vagy „kockás” karakterekhez vezethet. Mindig expliciten adjuk meg a kódolást (pl. UTF-8).
- Teljesítményproblémák intenzív string összefűzésnél: Ha sok string összefűzési műveletet végzünk (különösen ciklusban), és nem használunk
StringBuilder
-t (vagyStringBuffer
-t), az komoly teljesítményromláshoz vezethet a sok ideiglenes string objektum létrehozása miatt.