Introduction : Une magie qui n'est pas due au hasard
\n\nSi vous avez déjà passé du temps sur Stack Overflow à chercher la réponse à un bug étrange, vous avez sûrement vu la question qui a rassemblé des milliers de vues et des débats animés : "Why does this code using random strings print 'hello world'?". Cela ressemble à une énigme, n'est-ce pas ? Comment des chaînes générées aléatoirement peuvent-elles former une salutation cohérente ?
\n\nDans cet article, nous ne nous contenterons pas de résoudre ce phénomène SEO (oui, c'est un excellent cas d'étude pour le référencement de contenu éducatif), mais nous le transformerons en une leçon complète sur Java. Vous apprendrez comment fonctionnent les pools de chaînes, pourquoi hashCode() réserve parfois des surprises, et quelles meilleures pratiques adopter en 2025 pour que votre code soit prévisible et efficace.
Prêts ? C'est parti !
\n\n1. Ce code célèbre : que se passe-t-il ?
\n\nRappelons l'exemple classique qui a fait exploser Stack Overflow. Imaginez que vous ayez une méthode qui génère des chaînes aléatoires et vérifie leur égalité :
\n\npublic class RandomStringTest {\n public static void main(String[] args) {\n String[] randomStrings = new String[1000];\n for (int i = 0; i < 1000; i++) {\n randomStrings[i] = generateRandomString();\n }\n \n for (String s : randomStrings) {\n if (s.equals("hello world")) {\n System.out.println("Found: " + s);\n }\n }\n }\n \n public static String generateRandomString() {\n // Une logique étrange\n return new StringBuilder()\n .append((char) (Math.random() * 256))\n .append((char) (Math.random() * 256))\n // ... beaucoup de caractères\n .toString();\n }\n}\n\n\nÀ première vue, la probabilité d'obtenir "hello world" par hasard est de (1/256)^11 — pratiquement nulle. Pourtant, le code imprime "hello world" ! Comment ? Le hasard n'y est pour rien. Le secret réside dans le pool de chaînes (String pool) et les particularités du hachage en Java.
\n\n2. La solution : String Pool et hashCode
\n\nEn Java, les chaînes sont des objets immuables. Lorsque vous créez une chaîne via un littéral ("hello world"), elle est placée dans le String pool — une zone mémoire spéciale. Si une autre chaîne fait référence à la même valeur, la JVM ne crée pas un nouvel objet, mais renvoie une référence à l'objet existant.
Mais dans notre exemple, les chaînes sont générées aléatoirement. Comment peuvent-elles quand même être égales ? Réponse : un hashCode() surchargé. Dans certaines versions de Java (notamment avant la version 8), l'algorithme de hachage des chaînes était prévisible et pouvait entraîner des collisions si les chaînes avaient la même longueur et la même composition de caractères. Cependant, la véritable magie opère lorsque le String pool utilise l'internement.
\n\nLorsque vous appelez s.equals("hello world"), la JVM peut optimiser la comparaison si les deux chaînes se trouvent dans le pool. Mais dans notre cas, les chaînes sont différentes... Ou pas ? En réalité, si vous regardez l'implémentation de generateRandomString() dans la question originale, il y avait une astuce : la méthode retournait une chaîne qui était toujours "hello world" à cause d'une erreur dans la logique de génération.
Voici un exemple de cette "aléatoire" :
\n\npublic static String generateRandomString() {\n Random random = new Random(42); // Seed fixe\n byte[] bytes = new byte[11];\n random.nextBytes(bytes);\n return new String(bytes);\n}\n\n\nSi la seed est fixe, la séquence "aléatoire" est toujours la même. Et si la seed est choisie de manière à générer "hello world" ? C'est la réponse à l'énigme ! Le code n'est pas aléatoire — il est déterministe.
\n\n