Cordes de Java: “String s = new String(”idiot“);”
Je suis une C++ gars de l'apprentissage de Java. Je suis en train de lire Efficace Java et quelque chose me troublait. Il est dit de ne jamais écrire le code comme ceci:
String s = new String("silly");
Parce qu'il crée inutile String
objets. Mais au lieu de cela, il devrait être écrit comme ceci:
String s = "No longer silly";
Ok bien loin...Cependant, compte tenu de cette classe:
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
:
:
}
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
-
Pourquoi est la première instruction ok? Ne devrait-elle pas être
CaseInsensitiveString cis = "Polish";
-
Comment puis-je faire
CaseInsensitiveString
se comportent comme desString
de sorte que la déclaration ci-dessus est OK (avec et sans l'extensionString
)? Quel est-il de Chaîne de fait, il est OK pour simplement être en mesure de passer un littéral comme ça? De ma compréhension, il n'existe pas de constructeur de copie" concept en Java?
- String str1 = "foo"; String ch2 = "foo"; les Deux str1 et str2 appartient à tha même objet String, "foo", b'coz pour Java gère les Chaînes dans StringPool, est donc une nouvelle variable se réfère à la même Chaîne, il n'est pas en créer un autre plutôt attribuer la même alerady présents dans StringPool. Mais lorsque nous faisons cela: String str1 = new String("toto"); String str2 = new String("toto"); Ici, les deux str1 et str2 appartient à différents Objets, b'coz new String() de force de créer un nouvel Objet de type String.
Vous devez vous connecter pour publier un commentaire.
String
est un spécial intégré dans la classe de la langue. Il est pour leString
classe seulement dans lequel vous devez éviter de le direParce que le littéral
"Polish"
est déjà de typeString
, et vous êtes en train de créer un inutile à l'objet. Pour toute autre classe, en disantest la bonne (et seulement dans ce cas) une chose à faire.
new String("foo")
, vous pouvez vous demander pourquoi le constructeurnew String(String)
existe. La réponse est qu'il est parfois bon de l'utiliser: stackoverflow.com/a/390854/1442870Je crois que le principal avantage de l'utilisation de la forme littérale (c'est à dire, "foo", plutôt que de new String("toto")), c'est que tous les littéraux de Chaîne sont des "internés" par la machine virtuelle. En d'autres termes, il est ajouté à un pool de telle sorte que tout autre code qui crée la même chaîne va utiliser la mise en commun de la Chaîne plutôt que de créer une nouvelle instance.
À titre d'exemple, le code suivant va imprimer vrai pour la première ligne, mais faux pour la seconde:
false
.Les chaînes de caractères sont traités un peu spécialement en java, ils sont immuables, de sorte qu'il est sûr pour eux d'être manipulés par de comptage de référence.
Si vous écrivez
alors s et t en fait référence à un même objet, et s==t renvoie true, pour "==" pour les objets de lecture "est le même objet" (ou peut, de toute façon, je ne suis pas sûr si c'est la partie de la langue spec ou tout simplement un détail de l'implémentation de compilateur-alors peut-être il n'est pas sûr de s'appuyer sur cette) .
Si vous écrivez
alors s!=t (parce que vous avez explicitement créé une nouvelle chaîne de caractères) même si l'article.est égal à(t) retourne vrai (car la chaîne ajoute ce comportement est égal).
La chose que vous voulez écrire,
ne peut pas travailler parce que vous êtes en train de penser que les citations sont une sorte de court-circuit du constructeur de votre objet, alors qu'en fait, cela ne fonctionne que pour plain old java.lang.Les chaînes de caractères.
strA = strB
, au lieu destrA = new String(strB)
. il n'a vraiment pas avoir à faire beaucoup avec de la ficelle en stage.littérale vont aller dans la piscine et s1 référerons.
cette fois, il coche la case "foo" littérale est déjà disponible dans StringPool ou pas comme aujourd'hui il existe donc s2 renverra le même littéral.
"foo" littérale sera créé dans StringPool d'abord, puis à travers string arg Chaîne du constructeur d'Objet sera créé-je.e "foo" dans le tas en raison de la création d'un objet par le biais de nouvelles opérateur s3 de le soumettre.
même que s3
donc
System.out.println(s1==s2);//**true** due to literal comparison.
et
System.out.println(s3==s4);//**false** due to object
comparaison(s3 et s4 est créé à différents endroits dans le tas)
String
s ont la particularité de Java - ils sont immuables, et des constantes de chaîne sont automatiquement transformés enString
objets.Il n'y a aucun moyen pour votre
SomeStringClass cis = "value"
exemple, pour appliquer à toute autre catégorie.Ni étendre
String
, parce qu'il est déclaré commefinal
, ce qui signifie pas de sous-classement est autorisé.Cordes de Java sont intéressants. On dirait les réponses ont couvert les points intéressants. Voici mes deux cents.
les chaînes sont immuables (vous ne pouvez jamais changer)
les comparaisons de chaînes sont conditionnels à ce que vous comparez
a1
n'est pas égale àa2
a1
eta2
sont les références de l'objetJe pense que vous êtes sur la mauvaise voie en essayant d'utiliser le caseinsensitive classe. Laisser les cordes seules. Ce qui vous préoccupe vraiment, c'est la façon dont vous affichez ou comparer les valeurs. Utiliser une autre classe pour le format de la chaîne ou de faire des comparaisons.
c'est à dire
Puisque vous faites de la classe, vous pouvez faire le compare à faire ce que vous voulez - comparer les valeurs de texte.
Vous ne pouvez pas. Des choses en double-guillemets en Java sont spécialement reconnu par le compilateur comme des Chaînes de caractères, et, malheureusement, vous ne pouvez pas remplacer ce (ou de prolonger
java.lang.String
- il déclaréfinal
).La meilleure façon de répondre à votre question serait de vous permettre de vous familiariser avec la "constante de Chaîne de la piscine". En java, les objets de chaîne sont immuables (j'.e leurs valeurs ne peuvent pas être modifiés une fois qu'ils sont initialisés), de sorte que lors de l'édition d'une chaîne de caractères de l'objet, en fin de création d'un nouveau édité objet string wherease l'ancien objet flotte autour de dans une mémoire spéciale ares appelle la "constante de chaîne de la piscine". la création d'un nouvel objet de type string par
ne fera que créer un objet de type string dans la piscine et la référence de la volonté de s'y référer, mais en utilisant
vous créez deux objets string: un dans la piscine, et l'autre dans le tas. la référence ne fait référence à l'objet dans le tas.
Assez, il a été dit dès le premier point. "Le polonais" est un littéral de chaîne et ne peut être attribuée à la CaseInsentiviveString classe.
Maintenant sur le deuxième point
Bien que vous ne pouvez pas créer de nouveaux littéraux, vous pouvez suivre le premier élément de ce livre pour un "semblable" approche si les affirmations suivantes sont vraies:
Voici le code.
//Test de la classe à l'aide de "faire valoir" mot-clé
Qui est, de créer un pool interne de CaseInsensitiveString objets, et le retour de la corrensponding exemple à partir de là.
De cette façon, le "==" opérateur retourne vrai pour deux objets de références, ce qui représente la même valeur.
Ceci est utile lorsque des objets semblables sont utilisés très fréquemment et en créant le coût est cher.
La classe string documentation indique que la classe utilise un pool interne
La classe n'est pas complète, quelques questions intéressantes se pose lorsque nous essayons de marcher le contenu de l'objet à la mise en œuvre de la CharSequence interface, mais ce code est assez bon pour montrer comment cet élément dans le Livre pourrait être appliquée.
Il est important de noter qu'en utilisant le internalPool objet, les références ne sont pas libérés et donc pas de garbage collector, et qui peut devenir un problème si beaucoup d'objets sont créés.
Il travaille pour la Chaîne de la classe parce qu'il est utilisé de manière intensive et la piscine est constituée de "internés" objet.
Il fonctionne bien pour la classe Boolean trop, parce qu'il y a seulement deux valeurs possibles.
Et enfin c'est aussi la raison pour laquelle valueOf(int) dans la classe Integer est limitée à -128 à 127 valeurs int.
Dans votre premier exemple, vous créez une Chaîne de caractères, "idiot", puis en le passant en paramètre à l'autre de la Chaîne de constructeur de copie, ce qui rend une deuxième Chaîne, qui est identique à la première. Depuis Java, les Chaînes sont immuables (quelque chose que, souvent, les piqûres des gens qui sont habitués à des chaînes C), ce est un gaspillage inutile de ressources. Vous devez utiliser à la place le deuxième exemple parce qu'il saute plusieurs étapes inutiles.
Cependant, la Chaîne de caractères littérale n'est pas un CaseInsensitiveString de sorte que l'on ne peut pas faire ce que vous voulez dans votre dernier exemple. En outre, il n'existe aucun moyen de surcharger un opérateur de coulée comme vous pouvez le faire en C++ donc il n'y a littéralement aucun moyen de faire ce que vous voulez. Vous devez, au lieu de le passer en paramètre à votre constructeur de la classe. Bien sûr, je serais probablement juste de l'utilisation de la Chaîne.toLowerCase() et être fait avec elle.
Aussi, votre CaseInsensitiveString devrait mettre en œuvre l'CharSequence interface ainsi que probablement le Serializable et Comparables sur les interfaces. Bien sûr, si vous mettez en œuvre Comparable, vous devez remplacer equals() et hashCode() en tant que bien.
Juste parce que vous avez le mot
String
dans votre classe, ne signifie pas que vous obtenez toutes les caractéristiques particulières de l'intégré dansString
classe.CaseInsensitiveString
n'est pas unString
bien qu'il contient unString
. UnString
littérale e.g "exemple" peut être affecté uniquement à unString
.CaseInsensitiveString et String sont des objets différents. Vous ne pouvez pas faire:
parce que "polonais" est une Chaîne de caractères, pas un CaseInsensitiveString. Si la Chaîne étendue CaseInsensitiveString Chaîne, alors vous seriez OK, mais de toute évidence il ne l'est pas.
Et ne vous inquiétez pas à propos de la construction ici, vous ne serez pas en faire des objets inutiles. Si vous regardez le code du constructeur, tout ce qu'il fait c'est de stocker une référence à la chaîne de caractères passée dans. Rien de plus est en cours de création.
Dans la String s = new String("toto") cas c'est de faire quelque chose de différent. Vous êtes le premier de la création de la chaîne littérale "foobar", puis la création d'une copie de celui-ci par la construction d'une nouvelle chaîne d'elle. Il n'y a pas besoin de créer cette copie.
quand ils disent d'écrire
au lieu de
qu'ils signifient pour la création d'un objet de type String parce que les deux phrases ci-dessus créer un objet de type String, mais la nouvelle Chaîne de caractères() version crée Chaîne de deux objets: l'un dans le tas et l'autre en constante chaîne de la piscine. Par conséquent, avec plus de mémoire.
Mais quand vous écrivez
vous n'êtes pas la création d'une Chaîne de caractères au lieu de cela, vous créez un objet de la classe CaseInsensitiveString. Par conséquent, vous devez utiliser l'opérateur new.
Si j'ai bien compris, votre question signifie pourquoi on ne peut pas créer un objet directement en lui assignant une valeur, permet de ne pas le restreindre à un Wrapper de la classe String en java.
Pour répondre, je dirais simplement, purement langages de Programmation Orientés Objet ont des constructions et il est dit, que tous les littéraux de les écrire, seul, peut être directement transformée en un objet d'un type donné.
Que signifie précisément, si l'interprète voit 3 il sera converti en un objet Integer parce que entier est le type est défini pour ces littéraux.
Si l'interprète voit quelque chose entre guillemets simples, comme "un", il permettra de créer directement un objet de type personnage, vous n'avez pas besoin de spécifier que c'est la langue définit la valeur par défaut de l'objet de type personnage pour elle.
De même, si l'interprète voit quelque chose de "", il sera considéré comme un objet de son type par défaut c'est à dire de la chaîne. C'est du code natif de travail en arrière-plan.
Grâce à MIT la vidéo cours magistral 6.00 où j'ai eu l'allusion à cette réponse.
En Java la syntaxe "texte" crée une instance de la classe java.lang.Chaîne de caractères. La mission:
est un simple devoir, pas de constructeur de copie nécessaire.
Est illégal ce que vous faites parce que la MyString classe n'est pas de java.lang.Chaîne ou une super-classe de java.lang.Chaîne de caractères.
Tout d'abord, vous ne pouvez pas faire une classe qui étend la classe de Chaîne, parce que String est une classe finale. Java et de gérer les Chaînes de caractères différent de celui des autres classes, donc uniquement avec de la Ficelle que vous pouvez faire
Mais de pentecôte de votre classe, vous devez appeler le constructeur. Donc, que le code est bien.
Je voudrais juste ajouter que Java a Copie des constructeurs...
Bien, c'est d'un ordinaire constructeur avec un objet de même type que l'argument.
Dans la plupart des versions du JDK, les deux versions sera le même:
String s = new String("idiot");
String s = "N'est plus ridicule";
Parce que les chaînes sont immuables, le compilateur gère une liste de constantes de chaîne et si vous essayez de faire une nouvelle on va d'abord vérifier si la chaîne est déjà défini. Si c'est une référence à l'actuel immuable la chaîne renvoyée est.
À préciser - quand vous dites "String s =" vous êtes la définition d'une nouvelle variable qui prend de la place sur la pile, puis si vous dites "Non plus idiot" ou de new String("idiot") exactement la même chose se produit - une nouvelle chaîne constante est compilé dans votre application et les points de référence pour qui.
Je ne vois pas la distinction ici. Cependant, pour votre propre classe, qui n'est pas immuable, ce comportement est hors de propos et vous devez appeler votre constructeur.
Mise à JOUR: j'ai eu tort!
Basée sur une baisse de vote et de commentaire ci-joints j'ai testé ce et de réaliser que ma compréhension est erronée - new String("Idiot"), en effet, créer une nouvelle chaîne plutôt que de réutiliser l'existant. Je ne sais pas pourquoi cela serait, quel est l'avantage?) mais le code parle plus fort que les mots!
Chaîne est l'une des classes spéciales dans laquelle vous pouvez créer sans la nouvelle Sring partie
c'est le même que
int x = y;
ou
char c;
C'est une loi fondamentale que les Chaînes de caractères en java sont immuables et sensibles à la casse.
Les deux str1 et str2 appartient à tha même objet String, "foo", b'coz Java gère les Chaînes dans StringPool, donc si une nouvelle variable se réfère à la même Chaîne, il n'est pas en créer un autre plutôt attribuer la même alerady présents dans StringPool.
Ici à la fois str1 et str2 appartient à différents Objets, b'coz new String() de force de créer un nouvel Objet de type String.
Java crée un objet String pour chaque littéral de chaîne que vous utilisez dans votre code. Tout moment
""
est utilisé, il est le même que l'appel à lanew String()
.Les chaînes de caractères sont des données complexes que simplement "agissent comme des données primitifs. Les littéraux de chaîne sont en fait des objets, même si nous faisons semblant qu'ils sont primitifs littéraux, comme
6, 6.0, 'c',
etc. Ainsi, la Chaîne "littérale""text"
renvoie un nouvel objet de type String avec la valeurchar[] value = {'t','e','x','t}
. Par conséquent, l'appelest en fait ressemble à l'appel de
Espérons-le, à partir d'ici, vous pouvez voir pourquoi votre manuel considère cette redondance.
Pour référence, voici la mise en œuvre de la Chaîne: http://www.docjar.com/html/api/java/lang/String.java.html
C'est un plaisir de lire et pourrait inspirer d'une idée. Il est également idéal pour les débutants à lire et à essayer de comprendre, comme le code montre très professionnelle et de la convention-code compatible.
Une autre bonne référence est le Java tutoriel sur les Chaînes:
http://docs.oracle.com/javase/tutorial/java/data/strings.html