55 votes

intern () se comporte différemment dans Java 6 et Java 7

 class Test
{
 public static void main(String... args)
 {
  String s1="Good";
  s1=s1+"morning";
  System.out.println(s1.intern());

  String s2="Goodmorning";
  if(s1==s2)
  {
    System.out.println("both are equal");
   }
  }
}
 

Ce code produit différentes sorties en Java 6 et Java 7. En Java 6, la condition s1==s2 renvoie false et en Java 7, les s1==s2 renvoie true . Pourquoi?

Pourquoi ce programme produit-il des sorties différentes en Java 6 et Java 7?

27voto

Carlos Heuberger Points 11804

Il semble que JDK7 processus de stagiaire dans une manière différente comme avant.
Je l'ai testé avec la version 1.7.0-b147 et a obtenu "les deux sont égaux", mais lors de l'exécution (même bytecode) avec 1,6.0_24 je ne reçois pas le message.
Il a également dépend de l'endroit où l' String b2 =... ligne est située dans le code source. Le code suivant n'a pas aussi de sortie le message:

class Test {
   public static void main(String... args) {
      String s1 = "Good";
      s1 = s1 + "morning";

      String s2 = "Goodmorning";
      System.out.println(s1.intern());  //just changed here s1.intern() and the if condition runs true   

      if(s1 == s2) {
         System.out.println("both are equal");
      } //now it works.
   }
}

il semble que l' intern après ne pas trouver le String dans sa piscine de chaînes, insère l'instance réelle s1 dans la piscine. La JVM est à l'aide de la piscine lorsque s2 est créé, il obtient la même référence que s1 dos. De l'autre côté, si s2 est créé en premier, que la référence est stockée dans la piscine.
Cela peut être à la suite du déménagement de l'interné fils de la génération permanente du tas Java.

Trouvé ici: Important RFEs Abordées dans le JDK 7

Dans le JDK 7, interné les chaînes ne sont plus attribués dans la génération permanente du tas Java, mais sont à la place allouée à la partie principale de la Java heap (connu comme les jeunes et les anciennes générations), avec les autres objets créés par l'application. Ce changement se traduira par plus de données résidant dans le principal segment Java, et moins de données dans la génération permanente, et peut donc exiger que les tailles de tas pour être ajusté. La plupart des applications ne verrez que très peu de différences dans l'utilisation du tas à cause de ce changement, mais de plus grandes applications qui se chargent de nombreuses classes ou de faire un usage intensif de la Chaîne.stagiaire() la méthode verra de plus en plus de différences significatives.

Pas sûr si c'est un bug et à partir de la version... Le JLS 3.10.5 unis

Le résultat explicitement interner une angiographie de la chaîne est la même chaîne que tous les pré-existantes chaîne littérale avec le même contenu.

donc, la question est de savoir comment pré-existant est interprété, au moment de la compilation ou de l'exécution en temps: "Goodmorning" pré-existant ou pas?
Je préfère la façon dont il a ÉTÉ mis en œuvre avant le 7...

26voto

Andrey Points 2962

Nous allons omettre des détails inutiles à partir de l'exemple:

class Test {
    public static void main(String... args) {
        String s1 = "Good";
        s1 = s1 + "morning";
        System.out.println(s1 == s1.intern()); // Prints true for jdk7, false - for jdk6.
    }
}

Considérons String#intern comme une boîte noire. Basée sur quelques cas de test à exécuter, j'en conclurai que la mise en œuvre est le suivant:

La version 6 de Java:
si la piscine contient de l'objet est égale à this, puis de retourner référence à cet objet, d'en créer de nouveaux chaîne (égal à this), de mettre à la piscine, et de retour référence à cette instance créée.

Java 7:
si la piscine contient de l'objet est égale à this, puis de retourner référence à cet objet, autre mis this à la piscine, et de revenir this.

Ni Java 6 et Java 7 rompt le contrat de la méthode.

Il semble que la nouvelle stagiaire de la méthode comportement est un résultat de la correction de ce bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6962931.

9voto

Nathan Hughes Points 30377

== compare les références. Le stagiaire méthode permet de s'assurer des chaînes de caractères avec la même valeur ont la même référence.

La javadoc de la Chaîne.stagiaire méthode explique:

public String stagiaire()

Renvoie une représentation canonique de l'objet string.

Une piscine de chaînes, initialement vide, est entretenu en privé, par le la classe String.

Lorsque le stagiaire méthode est invoquée, si la piscine contient déjà un chaîne égale à cette Chaîne de l'objet tel que déterminé par la equals(Object) la méthode de la corde de la piscine est retourné. Sinon, cette Objet de chaîne est ajoutée à la piscine et une référence à cette Chaîne l'objet est retourné.

Il s'ensuit que pour tout deux chaînes de s et t, s.stagiaire() == t.stagiaire() est vrai si et seulement si s.est égal à(t) est vrai.

Toutes les chaînes littérales et de la chaîne de valeur de la constante d'expressions interné. Les littéraux de chaîne sont définies dans le §3.10.5 du Langage Java Spécification

Retourne: une chaîne qui a le même contenu, comme cette chaîne, mais est garanti à partir d'un pool de chaînes uniques.

Donc, sans s'y consacrant le compilateur regarde les constantes dans le code java et s'appuie sur sa constante de la piscine. Il y a une autre piscine entretenue par la classe String, et un stage contrôles de la chaîne transmise à l'encontre de la piscine et permet de s'assurer de la référence est unique (de sorte que == travail).

7voto

Mohammad Faisal Points 1769

Dans jdk6: String s1="Good"; crée un objet String "Bon", en constante piscine.

s1=s1+"morning"; crée un autre objet de type String "matin" en constante piscine mais cette fois réellement JVM n': s1=new StringBuffer().append(s1).append("morning").toString();.

Maintenant que l' new opérateur crée un objet dans le tas, par conséquent, la référence en s1 est de tas pas constant, piscine et l' String s2="Goodmorning"; crée un objet String "Goodmorning" en constante piscine dont la référence est stockée dans s2.

Par conséquent, if(s1==s2) condition est fausse.

Mais ce qui se passe dans jdk7?

6voto

Sachin Karjatkar Points 308

PREMIER CAS:

Dans le premier code ciselée vous sont effectivement l'ajout de trois Chaînes de caractères dans la Piscine de Chaînes de caractères. 1. s1 = "Bon"
2. s1 = "Goodmorning" (après la concaténation) 3. s2 = "Goodmorining"

Tout en faisant if(s1==s2), les objets sont les mêmes, mais il y a aussi différents donc c'est faux.

DEUXIÈME CAS:

Dans ce cas, vous utilisez s1.stagiaire(), ce qui implique que si la piscine contient déjà une chaîne égale à cette Chaîne de l'objet tel que déterminé par la equals(Object) méthode de la corde de la piscine est retourné. Sinon, cette Chaîne de l'objet est ajouté à la piscine et une référence à cet objet String est retourné.

  1. s1 = "Bon"
  2. s1 = "Goodmorning" (après la concaténation)
  3. Pour String s2="Goodmorning", la nouvelle Chaîne n'est pas ajouté à la piscine, et obtenir une référence d'un s2. Par conséquent, si(s1==s2) renvoie la valeur true.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X