Selon String # intern () , la intern
méthode est censée renvoyer la chaîne à partir du pool de chaînes si la chaîne est trouvée dans le pool de chaînes, sinon un nouvel objet de chaîne sera ajouté dans le pool de chaînes et la référence de cette chaîne est renvoyée.
Alors j'ai essayé ceci:
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
Je m'attendais à ce que ce s1 and s3 are same
soit imprimé car s3 est interné, et s1 and s2 are same
ne sera pas imprimé. Mais le résultat est: les deux lignes sont imprimées. Cela signifie que, par défaut, les constantes String sont internées. Mais si c'est le cas, pourquoi avons-nous besoin de la intern
méthode? En d'autres termes, quand devrions-nous utiliser cette méthode?
java
string
string-interning
Rakesh Juyal
la source
la source
intern
comme méthode publique. Ne devrions-nous pas avoirintern
comme méthode privée, pour que personne ne puisse y avoir accès. Ou y a-t-il un but de cette méthode?Réponses:
Java intègre automatiquement les littéraux String. Cela signifie que dans de nombreux cas, l'opérateur == semble fonctionner pour les chaînes de la même manière qu'il le fait pour les entiers ou d'autres valeurs primitives.
Puisque l'internalisation est automatique pour les littéraux de chaîne, la
intern()
méthode doit être utilisée sur les chaînes construites avecnew String()
En utilisant votre exemple:
String s1 = "Rakesh"; String s2 = "Rakesh"; String s3 = "Rakesh".intern(); String s4 = new String("Rakesh"); String s5 = new String("Rakesh").intern(); if ( s1 == s2 ){ System.out.println("s1 and s2 are same"); // 1. } if ( s1 == s3 ){ System.out.println("s1 and s3 are same" ); // 2. } if ( s1 == s4 ){ System.out.println("s1 and s4 are same" ); // 3. } if ( s1 == s5 ){ System.out.println("s1 and s5 are same" ); // 4. }
retournera:
Dans tous les cas en plus de
s4
variable, une valeur pour laquelle a été explicitement créée à l'aide de l'new
opérateur et où laintern
méthode n'a pas été utilisée sur son résultat, c'est une seule instance immuable qui est retournée dans le pool de constantes de chaîne de la JVM .Reportez-vous à JavaTechniques «Égalité des chaînes et internement» pour plus d'informations.
la source
String s1 = "Rakesh";
premier OB1String s4 = new String("Rakesh");
Deuxième OB2 Donc, le reste de (s2, s3, s5) fait référence au même objet (OB1) créé dans `` string Pool '' Alors puis-je dire que la.intern()
méthode utilisée pour empêcher de créer un nouvel objet si la même chaîne est disponible dansstring pool
If mon hypothèse est fausse alors donnez-moi une direction.Sur un projet récent, d'énormes structures de données ont été configurées avec des données lues à partir d'une base de données (et donc pas de constantes / littéraux de chaîne) mais avec une énorme quantité de duplication. C'était une application bancaire, et des choses comme les noms d'un ensemble modeste (peut-être 100 ou 200) sociétés apparaissaient partout. Les structures de données étaient déjà volumineuses, et si tous ces noms de corp avaient été des objets uniques, ils auraient débordé de mémoire. Au lieu de cela, toutes les structures de données avaient des références aux mêmes 100 ou 200 objets String, économisant ainsi beaucoup d'espace.
Un autre petit avantage des chaînes internes est qu'elles
==
peuvent être utilisées (avec succès!) Pour comparer des chaînes si toutes les chaînes impliquées sont garanties d'être internées. Outre la syntaxe allégée, il s'agit également d'une amélioration des performances. Mais comme d’autres l’ont souligné, cela comporte un grand risque d’introduire des erreurs de programmation, et cela ne devrait donc être fait qu’en dernier recours.L'inconvénient est que l'internement d'une chaîne prend plus de temps que de simplement la jeter sur le tas, et que l'espace pour les chaînes internes peut être limité, en fonction de l'implémentation Java. Il vaut mieux le faire lorsque vous avez affaire à un nombre raisonnable connu de chaînes avec de nombreuses duplications.
la source
The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limited
même si vous n'utilisez pas la méthode interne pour la constante String, elle sera automatiquement internée.==
cordes cependant.Je veux ajouter mes 2 cents sur l'utilisation
==
avec des chaînes internes.La première chose à
String.equals
faire estthis==object
.Donc, bien qu'il y ait un gain de performance minuscule (vous n'appelez pas de méthode), du point de vue du mainteneur, l'utilisation
==
est un cauchemar, car certaines chaînes internées ont tendance à devenir non internées.Je suggère donc de ne pas compter sur le cas particulier des
==
chaînes internes, mais de toujours les utiliserequals
comme Gosling l'a prévu.EDIT: internés devenant non internés:
V1.0 public class MyClass { private String reference_val; ... private boolean hasReferenceVal ( final String[] strings ) { for ( String s : strings ) { if ( s == reference_val ) { return true; } } return false; } private void makeCall ( ) { final String[] interned_strings = { ... init with interned values ... }; if ( hasReference( interned_strings ) ) { ... } } }
Dans la version 2.0, le mainteneur a décidé de rendre
hasReferenceVal
public, sans entrer dans les détails, qu'il attend un tableau de chaînes internes.V2.0 public class MyClass { private String reference_val; ... public boolean hasReferenceVal ( final String[] strings ) { for ( String s : strings ) { if ( s == reference_val ) { return true; } } return false; } private void makeCall ( ) { final String[] interned_strings = { ... init with interned values ... }; if ( hasReference( interned_strings ) ) { ... } } }
Vous avez maintenant un bogue, qui peut être très difficile à trouver, car dans la majorité des cas, le tableau contient des valeurs littérales et parfois une chaîne non littérale est utilisée. Si
equals
on a utilisé au lieu de==
puishasReferenceVal
aurait encore continuer à travailler. Encore une fois, le gain de performances est minime, mais le coût de maintenance est élevé.la source
Les littéraux de chaîne et les constantes sont internés par défaut. Autrement dit,
"foo" == "foo"
(déclaré par les littéraux String), maisnew String("foo") != new String("foo")
.la source
intern
,String literals and constants are interned by default
:, est correcte.new String("foo")
-> Ici, un littéral String "foo" est créé dans le pool String et un dans le tas, donc 2 objets au total sont créés.Apprendre Java String Intern - une fois pour toutes
Les chaînes en java sont des objets immuables de par leur conception. Par conséquent, deux objets chaîne, même avec la même valeur, seront des objets différents par défaut. Cependant, si nous souhaitons économiser de la mémoire, nous pourrions indiquer d'utiliser la même mémoire par un concept appelé string intern.
Les règles ci-dessous vous aideront à comprendre le concept en termes clairs:
Exemple:
String s1=new String (“abc”); String s2=new String (“abc”); If (s1==s2) //would return false by rule #4 If (“abc” == “a”+”bc” ) //would return true by rules #2 and #3 If (“abc” == s1 ) //would return false by rules #1,2 and #4 If (“abc” == s1.intern() ) //would return true by rules #1,2,4 and #6 If ( s1 == s2.intern() ) //wound return false by rules #1,4, and #6
Remarque: Les cas de motivation pour string intern ne sont pas abordés ici. Cependant, la sauvegarde de la mémoire sera certainement l'un des principaux objectifs.
la source
vous devriez faire deux périodes de temps qui sont le temps de compilation et le temps d'exécution, par exemple:
//example 1 "test" == "test" // --> true "test" == "te" + "st" // --> true //example 2 "test" == "!test".substring(1) // --> false "test" == "!test".substring(1).intern() // --> true
d'une part, dans l'exemple 1, nous trouvons que les résultats sont tous retournés true, car au moment de la compilation, le jvm mettra le "test" dans le pool de chaînes littérales, si le jvm find "test" existe, alors il utilisera celui qui existe, dans l'exemple 1, les chaînes "test" pointent toutes vers la même adresse mémoire, donc l'exemple 1 retournera vrai. en revanche, dans l'exemple 2, la méthode de substring () s'exécute au moment de l'exécution, dans le cas de "test" == "! test" .substring (1), le pool créera deux objets string, " test "et"! test ", donc ce sont des objets de référence différents, donc ce cas retournera faux, dans le cas de" test "=="! test ".substring (1) .intern (), la méthode de intern ( ) placera le ""! test ".substring (1)" dans le pool de chaînes littérales,
la source
http://en.wikipedia.org/wiki/String_interning
l'internation de chaînes est une méthode de stockage d'une seule copie de chaque valeur de chaîne distincte, qui doit être immuable. L'intégration de chaînes rend certaines tâches de traitement de chaînes plus efficaces en termes de temps ou d'espace, au prix de nécessiter plus de temps lorsque la chaîne est créée ou internée. Les valeurs distinctes sont stockées dans un pool interne de chaînes.
la source
Les chaînes internes évitent les chaînes en double. L'intégration économise de la RAM au détriment de plus de temps CPU pour détecter et remplacer les chaînes en double. Il n'y a qu'une seule copie de chaque chaîne qui a été internée, quel que soit le nombre de références qui la pointent. Étant donné que les chaînes sont immuables, si deux méthodes différentes utilisent accidentellement la même chaîne, elles peuvent partager une copie de la même chaîne. Le processus de conversion des chaînes dupliquées en chaînes partagées s'appelle interning.String.intern () vous donne l'adresse de la chaîne maître canonique. Vous pouvez comparer des chaînes internes avec un simple == (qui compare des pointeurs) au lieu d' égauxqui compare les caractères de la chaîne un par un. Étant donné que les chaînes sont immuables, le processus interne est libre d'économiser davantage d'espace, par exemple, en ne créant pas de littéral String distinct pour "pot" lorsqu'il existe en tant que sous-chaîne d'un autre littéral tel que "hippopotame".
Pour en savoir plus http://mindprod.com/jgloss/interned.html
la source
String s1 = "Anish"; String s2 = "Anish"; String s3 = new String("Anish"); /* * When the intern method is invoked, if the pool already contains a * string equal to this String object as determined by the * method, then the string from the pool is * returned. Otherwise, this String object is added to the * pool and a reference to this String object is returned. */ String s4 = new String("Anish").intern(); if (s1 == s2) { System.out.println("s1 and s2 are same"); } if (s1 == s3) { System.out.println("s1 and s3 are same"); } if (s1 == s4) { System.out.println("s1 and s4 are same"); }
PRODUCTION
la source
String p1 = "example"; String p2 = "example"; String p3 = "example".intern(); String p4 = p2.intern(); String p5 = new String(p3); String p6 = new String("example"); String p7 = p6.intern(); if (p1 == p2) System.out.println("p1 and p2 are the same"); if (p1 == p3) System.out.println("p1 and p3 are the same"); if (p1 == p4) System.out.println("p1 and p4 are the same"); if (p1 == p5) System.out.println("p1 and p5 are the same"); if (p1 == p6) System.out.println("p1 and p6 are the same"); if (p1 == p6.intern()) System.out.println("p1 and p6 are the same when intern is used"); if (p1 == p7) System.out.println("p1 and p7 are the same");
Lorsque deux chaînes sont créées indépendamment,
intern()
vous permet de les comparer et vous aide également à créer une référence dans le pool de chaînes si la référence n'existait pas auparavant.Lorsque vous utilisez
String s = new String(hi)
, java crée une nouvelle instance de la chaîne, mais lorsque vous utilisezString s = "hi"
, java vérifie s'il y a une instance du mot "hi" dans le code ou non et si elle existe, il renvoie simplement la référence.Étant donné que la comparaison de chaînes est basée sur une référence, elle vous
intern()
aide à créer une référence et vous permet de comparer le contenu des chaînes.Lorsque vous utilisez
intern()
dans le code, il efface l'espace utilisé par la chaîne faisant référence au même objet et renvoie simplement la référence du même objet déjà existant en mémoire.Mais dans le cas de p5 lorsque vous utilisez:
String p5 = new String(p3);
Seul le contenu de p3 est copié et p5 est créé à nouveau. Il n'est donc pas interné .
Ainsi, la sortie sera:
la source
public static void main(String[] args) { // TODO Auto-generated method stub String s1 = "test"; String s2 = new String("test"); System.out.println(s1==s2); //false System.out.println(s1==s2.intern()); //true --> because this time compiler is checking from string constant pool. }
la source
La méthode string intern () est utilisée pour créer une copie exacte de l'objet chaîne de tas dans le pool de constantes de chaîne. Les objets chaîne du pool de constantes chaîne sont automatiquement internés, mais les objets chaîne du tas ne le sont pas. L'utilisation principale de la création de stagiaires est d'économiser de l'espace mémoire et d'effectuer une comparaison plus rapide des objets chaîne.
Source: Qu'est-ce que string intern en java?
la source
Comme vous l'avez dit, cette
intern()
méthode de chaîne trouvera d'abord à partir du pool de chaînes, si elle le trouve, elle retournera l'objet qui pointe vers cela ou ajoutera une nouvelle chaîne dans le pool.String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hello".intern(); String s4 = new String("Hello"); System.out.println(s1 == s2);//true System.out.println(s1 == s3);//true System.out.println(s1 == s4.intern());//true
Le
s1
ets2
sont deux objets pointant vers le pool de chaînes "Hello", et en utilisant"Hello".intern()
le trouveras1
ets2
. Donc"s1 == s3"
renvoie true, ainsi que les3.intern()
.la source
En utilisant la référence d'objet de tas si nous voulons obtenir la référence d'objet de pool constante de chaîne correspondante , nous devrions alors opter pour intern ()
String s1 = new String("Rakesh"); String s2 = s1.intern(); String s3 = "Rakesh"; System.out.println(s1 == s2); // false System.out.println(s2 == s3); // true
Vue picturale
Étape 1: L' objet avec les données 'Rakesh' est créé dans le pool de constantes de tas et de chaînes. De plus, s1 pointe toujours vers l'objet du tas.
Étape 2: En utilisant la référence d'objet de tas s1, nous essayons d'obtenir la référence d'objet de réserve constante de chaîne correspondante s2, en utilisant intern ()
Étape 3: Création intentionnelle d'un objet avec les données 'Rakesh' dans le pool de constantes de chaîne, référencé par le nom s3
En tant qu'opérateur "==" destiné à la comparaison de références.
Obtenir faux pour s1 == s2
Obtenir vrai pour s2 == s3
J'espère que cette aide !!
la source