Java - String a metoda intern()
Jelikož se na různých místech v aplikaci vyskytují co do obsahu stejné řetězce, tak aby nedocházelo k plýtvání pamětí a ke ztrátám na výkonu režijemi, udržuje si Java tyto řetězce ve speciálním pool. Stejné řetězce jsou po nějaké "chvíli" po vytvoření, jestli ne hned, uloženy do tohoto pool. Když si tedy zažádáme (např.: vytváříme String s = "HelloWorld") o nějaký takový řetězec, je nám vrácen ten, který byl do poolu uložen.
Příklad:
String helloWorld = "HelloWorld";
helloWorld = helloWorld.intern();
intern() - Tato metoda souvisí s tím, že String se v aplikacích docela často používá a má proto trochu speciální zacházení ze strany překladače i JVM. Z důvodu výkonostního.
Metoda intern() dělá to, že uloží řetězec do tohoto poolu, nebo pokud už tam jiný String se stejným obsahem je, vrátí ten String z poolu. Ten speciální případ, kdy s používá pool je, když vytvoříte nový String pomocí literálu v Javě, tedy např.
String helloWorld = "HelloWorld";
Metoda intern() tedy slouží k uložení do poolu pro případ, že String vznikl nějak jinak. Celé to má význam pro ušetření paměti a urychlení porovnání Stringů (metodou equals()). Když vytvoříte dva Stringy se stejným obsahem
String helloWorld = "HelloWorld"; a String helloWorld2 = "HelloWorld";
bude to ve skutečnosti jeden objekt a ušetří se paměť. Při porovnání na equals(), se nejprve porovná identita (==) a teprve pokud nesouhlasí, porovnává se znak po znaku. Z toho plyne, že pokud jde o dva stejné objekty, porovnání na identitu je rychlejší.
Na druhé straně, využití metody inter() není tak akutní jak se zdá. Jednak vyvolání String.intern() nějakou dobu trvá a jednak není dost jasné jak se algoritmus pro ulkádání řetězců zachová.
Nabízejí se tedy dvě možnosti:
1. První je zavolat na String intern() a zaručit že String zůstane v poolu navěky. Tímto postupem by mohla dojít paměť...
2. Za druhé String, na který bylo zavoláno intern() zůstáva v pool do té doby, dokud je na něj reference. Tím je volání metody intern() více méně zbytečné a volání této metody vás jen brzdí.
Využívat intern() je tedy vhodné jen tehdy, když víte že daný řetězec v paměti potřebujete a chcete vědět, že ho tam i máte.
A kdo tedy pochopil o co jde, bude schopen správně udělat následující test. Co vypíše následující kód?
String hello1 = "hello";
String hello2 = new String("hello");
System.out.println(hello1 == hello2);
System.out.println(hello1 == (String)hello2);
System.out.println(hello1 == hello2.toString());
System.out.println(hello1 == hello2.toString().intern());
System.out.println(new String(hello1) == hello2);
System.out.println(hello1 == hello2.intern());
System.out.println(new String(hello1) == hello2.intern());
System.out.println(new String(hello1).intern() == hello2.intern());
Příklad:
String helloWorld = "HelloWorld";
helloWorld = helloWorld.intern();
intern() - Tato metoda souvisí s tím, že String se v aplikacích docela často používá a má proto trochu speciální zacházení ze strany překladače i JVM. Z důvodu výkonostního.
Metoda intern() dělá to, že uloží řetězec do tohoto poolu, nebo pokud už tam jiný String se stejným obsahem je, vrátí ten String z poolu. Ten speciální případ, kdy s používá pool je, když vytvoříte nový String pomocí literálu v Javě, tedy např.
String helloWorld = "HelloWorld";
Metoda intern() tedy slouží k uložení do poolu pro případ, že String vznikl nějak jinak. Celé to má význam pro ušetření paměti a urychlení porovnání Stringů (metodou equals()). Když vytvoříte dva Stringy se stejným obsahem
String helloWorld = "HelloWorld"; a String helloWorld2 = "HelloWorld";
bude to ve skutečnosti jeden objekt a ušetří se paměť. Při porovnání na equals(), se nejprve porovná identita (==) a teprve pokud nesouhlasí, porovnává se znak po znaku. Z toho plyne, že pokud jde o dva stejné objekty, porovnání na identitu je rychlejší.
Na druhé straně, využití metody inter() není tak akutní jak se zdá. Jednak vyvolání String.intern() nějakou dobu trvá a jednak není dost jasné jak se algoritmus pro ulkádání řetězců zachová.
Nabízejí se tedy dvě možnosti:
1. První je zavolat na String intern() a zaručit že String zůstane v poolu navěky. Tímto postupem by mohla dojít paměť...
2. Za druhé String, na který bylo zavoláno intern() zůstáva v pool do té doby, dokud je na něj reference. Tím je volání metody intern() více méně zbytečné a volání této metody vás jen brzdí.
Využívat intern() je tedy vhodné jen tehdy, když víte že daný řetězec v paměti potřebujete a chcete vědět, že ho tam i máte.
A kdo tedy pochopil o co jde, bude schopen správně udělat následující test. Co vypíše následující kód?
String hello1 = "hello";
String hello2 = new String("hello");
System.out.println(hello1 == hello2);
System.out.println(hello1 == (String)hello2);
System.out.println(hello1 == hello2.toString());
System.out.println(hello1 == hello2.toString().intern());
System.out.println(new String(hello1) == hello2);
System.out.println(hello1 == hello2.intern());
System.out.println(new String(hello1) == hello2.intern());
System.out.println(new String(hello1).intern() == hello2.intern());

