Accueil
Java Standard Edition
Java EE 5
Visual Basic .Net 2005
Visual C++ .Net 2005
Visual C# .Net 2005
Cours ASP .Net 2.0
Postgresql
Linux
Visual Studio 2008
ASP 3.0 Classique
Cours Javascript - DOM - DHTML
Cours Ajax
VBA
Assembleur
Perl
Membres
L'auteur du site
Nouveautés sur le site
Contacts
Plan du site
Exécution d'un programme
Les archives Jar
Les classes abstraites
Les interfaces
Les tableaux
La généricité
Les énumérations
Les classes internes
Classes anonymes et internes locales
Les threads: généralités
Les threads(2): synchronisation
E/S(1):InputStream et OutputStream
E/S(2):FileInputStream et FileOutputStream
E/S(3):Reader et Writer
E/S(4):FilterInputStream et FilterOutputStream
E/S(5):Les filtres d'octets: PrintStream
E/S(6):Les filtres d'octets: DataInputStream et DataOutputStream
E/S(7):Les filtres d'octets: BufferedInputStream et BufferedOutputStream
E/S(8):Flux de caractères: PrintWriter
E/S(9):Flux de caractères: FilterReader et FilterWriter
E/S(10):Flux de caractères: InputStreamReader, OutputStreamWriter, StreamDecoder, StreamEncoder
E/S(11):Flux de caractères: BufferedReader et BufferedWriter
E/S(12):Flux de caractères: FileReader et FileWriter
La classe String (java.lang)
Les collections: L'interface Collection(java.lang)
Les collections(2): L'interface List(java.util)
Les collections(3): AbstractCollection(java.util)
Les collections(4): AbstractList(java.util)
La bibliothèque Swing en Java
Les bases de données en Java
JDBC ( Java Database Connectivity )
Les interfaces graphiques
Les fichiers de configuration en Java
INSTALLATION JAVA EE 5, JRE 6, ECLIPSE, TOMCAT, ETC SOUS LINUX
INSTALLATION JAVA EE 5, JRE 6, ECLIPSE, TOMCAT, ETC SOUS WINDOWS
Les applications Web en java
Les filtres Java (javax.servlet.Filter)
I Généralités
I.1 Le formulaire principal
I.2 Les objets créés par Visual
I.3 Les variables références
I.4 Le garbage collector
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Applications winforms
I.2 Applications MFC
I.3 Objets managés ou pas
I.4 Objets non managés
I.5 Objets managés - handle
I.6 Le top-level ^
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Puissant et Accessible
I.2 Créer ses classes
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
III Les services Windows
IV Le .net remoting
V Communication Tcp avec TcpClient et TcpListener
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Un EDI formidable
I.2 Inclure C# ou VB
I.3 L'objet Response
I.4 Les évènements
II ASP .net et les bdd
II.1 Essayer plusieurs fois la requête
I 2.1 Fichiers distincts
I.2.2 Avec la balise script
I.2.3 Inclure réellement
I.2.4 Avec Response.Write()
I.3.1 La méthode Response.Redirect()
I.4.1 Résoudre problème post
Installation Postgre Linux
Cours Postgresql
Le Shell Unix( Linux, Ubuntu)
Les scripts C-Shell
Programmation système Unix
Reseau Linux
Les iptables
Windows Presentation Foundation(WPF)
Le Framework 3.0
Windows Workflow Foundation(WF)
ASP 3.0 Classique
Cours Javascript - DOM - DHTML
Chat Ajax
VBA Excel 2003
Assembleur
Perl
Inscription
Liste membres
Livre d'or
Forum
Accueil
>
Java Standard Edition
>
La classe String (java.lang)
____________________________________________________________________________________________________
Connexion
La classe String (java.lang)
Sommaire :
I) Généralités
II) Le fonctionnement de la classe String (java.lang)
II-1) L'interface CharSequence (java.lang)
II-2) L'interface Comparable
(java.lang)
II-3) L'interface Serializable (java.io)
II-4) Attributs private de String
II-5) Constructeurs de String
II-6) Des méthodes de String
II-7) la méthode hashCode de String - Définition rapide du hashcode
Ce chapitre constitue des remarques sur l'implémentation de la classe String.
I) Généralités
" The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:
String str = "abc";
is equivalent to:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
"
La classe String représente les chaînes de caractères. Les littéraux chaînes de caractères dans les programmes Java, comme "abc", sont implémentés comme des instances de cette classe.
Les String sont constantes; leur valeur ne peut pas être changée après qu'elles ont été créées. La classe StringBuffer supporte les chaînes muables. Parce que les objets String sont immuables, ils peuvent être partagés.
Ne croyez pas que, parce qu'on peut écrire
String varChaine = "maChaine"; varChaine = "nouvelle";
que les String peuvent être modifiées. Lorsqu'on écrit "maChaine", on crée un objet String en mémoire, et on met sa référence dans la variable varChaine. Puis, en écrivant varChaine="nouvelle", l'objet String "maChaine" reste en mémoire, mais n'est plus référencé par personne (il sera donc détruit par le garbage collector quand il passera).
Un nouvel objet String, valant "nouvelle", est créé en mémoire, puis sa référence est mise dans la variable varChaine. On n'a donc pas pu modifier varChaine, en réalité, on a juste mis dans varChaine un autre objet String.
"The class String includes methods for examining individual characters of the sequence, for comparing strings, for searching strings, for extracting substrings, and for creating a copy of a string with all characters translated to uppercase or to lowercase. Case mapping relies heavily on the information provided by the Unicode Consortium's Unicode 3.0 specification. The specification's UnicodeData.txt and SpecialCasing.txt files are used extensively to provide case mapping.
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuffer class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.
Unless otherwise noted, passing a null argument to a constructor or method in this class will cause a NullPointerException to be thrown. "
La classe String inclut des méthodes pour examiner des caractères individuels de la séquence, pour comparer des String, pour rechercher des chaînes, pour extraire des sous-chaînes, et pour créer une copie de chaîne en ayant converti tous les caractères en majuscules ou minuscules.
La concaténation de String est implémentée dans la classe StringBuffer et sa méthode append.
Remarquez que StringBuffer stocke la valeur de sa chaîne aussi sous forme de tableau de caractères, et qu'il agrandit la taille de son tableau interne(en créant un tableau plus grand et en recopiant les caractères) en cas de concaténation avec append. Un nouvel objet tableau est donc en réalité créé, mais on peut dire que son tableau interne n'est pas immuable(même si c'est un nouvel objet, la référence du tableau interne change).
Et l'objet String est resté le même, alors qu'elle représente une autre chaîne; c'est juste l'objet pour son tableau interne qui a changé.
Alors que la référence du tableau interne d'une String ne changera jamais, pour un même objet String. Et surtout, pour un certain objet String initialisé au départ, on ne pourra jamais lui faire représenter une autre chaîne de caractères.
Les conversions en chaînes de caractères sont implémentées à travers la méthode toString, définie par la classe Object, qui est héritée par toutes les classes en Java.
II) Le fonctionnement de la classe String (java.lang)
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
Remarquez le "final", pour empêcher d'hériter de cette classe.
II-1) L'interface CharSequence (java.lang)
* @(#)CharSequence.java 1.9 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.lang; /** (...) * * @author Mike McCloskey * @version 1.9 05/11/17 * @since 1.4 * @spec JSR-51 */ public interface CharSequence { /** * Returns the length of this character sequence. The length is the number * of 16-bit <code>char</code>s in the sequence.</p> * * @return the number of <code>char</code>s in this sequence */ int length(); /** * Returns the <code>char</code> value at the specified index. An index ranges from zero * to <tt>length() - 1</tt>. The first <code>char</code> value of the sequence is at * index zero, the next at index one, and so on, as for array * indexing. </p> * * <p>If the <code>char</code> value specified by the index is a * <a href="Character.html#unicode">surrogate</a>, the surrogate * value is returned. * * @param index the index of the <code>char</code> value to be returned * * @return the specified <code>char</code> value * * @throws IndexOutOfBoundsException * if the <tt>index</tt> argument is negative or not less than * <tt>length()</tt> */ char charAt(int index); /** * Returns a new <code>CharSequence</code> that is a subsequence of this sequence. * The subsequence starts with the <code>char</code> value at the specified index and * ends with the <code>char</code> value at index <tt>end - 1</tt>. The length * (in <code>char</code>s) of the * returned sequence is <tt>end - start</tt>, so if <tt>start == end</tt> * then an empty sequence is returned. </p> * * @param start the start index, inclusive * @param end the end index, exclusive * * @return the specified subsequence * * @throws IndexOutOfBoundsException * if <tt>start</tt> or <tt>end</tt> are negative, * if <tt>end</tt> is greater than <tt>length()</tt>, * or if <tt>start</tt> is greater than <tt>end</tt> */ CharSequence subSequence(int start, int end); /** * Returns a string containing the characters in this sequence in the same * order as this sequence. The length of the string will be the length of * this sequence. </p> * * @return a string consisting of exactly this sequence of characters */ public String toString(); }
"A CharSequence is a readable sequence of char values. This interface provides uniform, read-only access to many different kinds of char sequences. A char value represents a character in the Basic Multilingual Plane (BMP) or a surrogate. Refer to Unicode Character Representation for details.
This interface does not refine the general contracts of the equals and hashCode methods. The result of comparing two objects that implement CharSequence is therefore, in general, undefined. Each object may be implemented by a different class, and there is no guarantee that each class will be capable of testing its instances for equality with those of the other. It is therefore inappropriate to use arbitrary CharSequence instances as elements in a set or as keys in a map.
Since:
1.4
"
Une CharSequence est une séquence lisible de caractères. Cette interface procure des moyens d'accès uniformes et read-only pour plusieurs types de séquences de caractères.
Cette interface ne procure pas de méthodes de comparaison ou de hashcode. Le résultat de la comparaison de deux objets implémentant CharSequence est, par conséquent, indéfini. Chaque objet de la classe CharSequence peut être implémenté par une classe différente, et il n'y a aucune garantie pour chaque classe qu'elle soit capable de tester, pour ses instances, l'égalité avec les instances de l'autre classe.
On comprend cette explication, comment implémenter dans une classe, une méthode de comparaison, capable de prendre en compte toutes les classes CharSequence, alors que de nouvelles pourront toujours être créées dans le futur?
Revenons sur le début de cette javadoc: une CharSequence procure des moyens d'accès uniforme. Prenons l'exemple de deux classes implémentant CharSequence: String(java.lang) et StringBuffer(java.lang). CharSequence nous procure des moyens uniformes de lire ces différents types de strings.
Remarquons l'apparition tardive de CharSequence( depuis 1.4).
II-2) L'interface Comparable<T> (java.lang)
* @(#)Comparable.java 1.26 06/04/21 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.lang; import java.util.*; (...) /** (...) * @param <T> the type of objects that this object may be compared to * * @author Josh Bloch * @version 1.26, 04/21/06 * @see java.util.Comparator * @since 1.2 */ public interface Comparable<T> { /** * Compares this object with the specified object for order. Returns a * negative integer, zero, or a positive integer as this object is less * than, equal to, or greater than the specified object. * (...) */ public int compareTo(T o); } "
"This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.
Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort). Objects that implement this interface can be used as keys in a sorted map or elements in a sorted set, without the need to specify a comparator
(...)"
Cette interface impose un total classement des objets de chaque classe qui l'implémentent. Ce classement est référencé comme étant le classement naturel de la classe, et la méthode compareTo est référencée comme étant sa méthode naturelle de comparaison.
Les listes( et tableaux) d'objets qui implémentent cette interface peuvent être triés automatiquement par Collections.sort (et Arrays.sort). Les objets qui implémentent cette interface peuvent être utilisés comme clés dans les map triées, ou comme éléments dans un ensemble trié, sans avoir besoin de spécifier un objet comparateur.
Il s'agit d'une interface générique. Pour la classe string, il s'agit de Comparable<String>. C'est-à-dire que String est obligé d'avoir une méthode public int compareTo( String o), qui compare donc la String courante et la String en paramètre.
Sur la méthode compareTo:
"Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.(...)"
La méthode compare l'objet courant avec l'objet spécifié en paramètre. Elle retourne un entier négatif, zéro, ou un entier positif selon que l'objet est inférieur, égal, ou supérieur à l'objet spécifié.
II-3) L'interface Serializable (java.io)
public interface Serializable
"(...) All subtypes of a serializable class are themselves serializable.The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.(...)"
Tous les sous-types d'une classe sérialisable sont eux-mêmes sérialisables. L'interface de sérialisation n'a pas de méthodes ou d'attributs, et sert seulement à indiquer la sémantique du fait d'être sérialisable.
On remarque que l'interface ne fournit pas les moyens de sérialiser l'objet, car elle ne sert pas à donner la façon de le sérialiser, mais juste à indiquer qu'on accepte que cet objet soit sérialisé.
Pour sérialiser un objet (sérialisable), on utilise la méthode writeObject de ObjectOutputStream(java.io); pour le lire ensuite, on se sert de readObject de ObjectInputStream( java.io).
" /* * @(#)Serializable.java 1.25 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.io; /** * Serializability of a class is enabled by the class implementing the * java.io.Serializable interface. Classes that do not implement this * interface will not have any of their state serialized or * deserialized. All subtypes of a serializable class are themselves * serializable. The serialization interface has no methods or fields * and serves only to identify the semantics of being serializable. <p> * (...) * @author unascribed * @version 1.25, 11/17/05 * @see java.io.ObjectOutputStream * @see java.io.ObjectInputStream * @see java.io.ObjectOutput * @see java.io.ObjectInput * @see java.io.Externalizable * @since JDK1.1 */ public interface Serializable { }
II-4) Attributs private de String
Regardons le début de la classe String:
/** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; /** Cache the hash code for the string */ private int hash; // Default to 0
Nous y voyons que la valeur interne de la String est en fait un tableau de caractères, nommé value.
offset est l'index de départ dans le tableau value.
count est le nombre de caractères de la chaîne.
II-5) Constructeurs de String
Regardons cet exemple de constructeur:
/** * Allocates a new {@code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * @param value * The initial value of the string */ public String(char value[]) { int size = value.length; this.offset = 0; this.count = size; this.value = Arrays.copyOf(value, size); }
Ce constructeur permet de créer une string à partir d'un tableau de caractères.
L'attribut offset est mis à 0. count vaut la taille du tableau en paramètre.
Dans le tableau interne de notre string, on crée un nouveau tableau de caractères avec la méthode statique Arrays.copyOf ( java.util), initialisé avec le contenu du tableau en paramètre.
II-6) Des méthodes de String
Voyons quelques méthodes de la classe String, pour connaître son fonctionnement.
/** * Copy characters from this string into dst starting at dstBegin. * This method doesn't perform any range checking. */ void getChars(char dst[], int dstBegin) { System.arraycopy(value, offset, dst, dstBegin, count); }
getChars utilise la méthode System.arraycopy, qui va recopier le contenu du tableau interne value de la String, à partir de l'index offset, et contenant count caractères, vers le tableau de caractères dest.
/** * Compares this string to the specified object. The result is {@code * true} if and only if the argument is not {@code null} and is a {@code * String} object that represents the same sequence of characters as this * object. * * @param anObject * The object to compare this {@code String} against * * @return {@code true} if the given object represents a {@code String} * equivalent to this string, {@code false} otherwise * * @see #compareTo(String) * @see #equalsIgnoreCase(String) */ public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; }
Voilà la méthode de comparaison d'égalité. En premier lieu, si les références des deux objets à comparer sont les mêmes, elle retourne true.
Puis, on vérifie que anObject est une instance de String. Ceci grâce à l'opérateur instanceof, qui vérifie que la classe indiquée est une des classes(ou interface bien sûr) dont hérite l'objet, ou la classe de l'objet lui-même. Puis on vérifie que les deux chaînes sont de la même longueur. Si c'est le cas, il ne nous reste plus qu'à comparer les valeurs des deux tableaux internes de caractères, en commençant par leurs offsets respectifs.
On fait la boucle autant de fois que la longueur, et on compare chaque caractère. Dès qu'on trouve une différence, on retourne false. A la fin de la boucle, on retourne true.
Regardons à présent la méthode concat:
/** * Concatenates the specified string to the end of this string. * <p> * If the length of the argument string is <code>0</code>, then this * <code>String</code> object is returned. Otherwise, a new * <code>String</code> object is created, representing a character * sequence that is the concatenation of the character sequence * represented by this <code>String</code> object and the character * sequence represented by the argument string.<p> * Examples: * <blockquote><pre> * "cares".concat("s") returns "caress" * "to".concat("get").concat("her") returns "together" * </pre></blockquote> * * @param str the <code>String</code> that is concatenated to the end * of this <code>String</code>. * @return a string that represents the concatenation of this object's * characters followed by the string argument's characters. */ public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } char buf[] = new char[count + otherLen]; getChars(0, count, buf, 0); str.getChars(0, otherLen, buf, count); return new String(0, count + otherLen, buf); }
Si la longueur de la 2e chaîne = 0, on retourne la référence de la première chaîne.
On peut noter que le framework accepte de retourner une référence sur le même objet. Mais comme on ne risque pas, avec les String, de modifier le contenu de l'objet, ce n'est pas gênant d'avoir deux variables qui pointent sur la même référence.
Sinon, on peut créer un nouveau tableau de caractères pour la future String résultante, de longueur égale à la somme des deux longueurs. Puis on copie dans le nouveau tableau, à l'aide de this.getChars, les caractères de la première String. Et enfin, on copie le tableau de la deuxième chaîne, dans la seconde partie du nouveau tableau, avec la méthode getChars de la deuxième String.
Il ne reste plus qu'à créer un nouvel objet String, avec le constructeur qui sait prendre en paramètre notre nouveau tableau de caractères.
II-7) la méthode hashCode de String - Définition rapide du hashcode
Le hash code est une valeur entière, qui permet de nous aider à tester rapidement que deux objets(d'une même classe) sont égaux. Deux objets sont égaux, si leurs méthodes hashCode retourne le même entier, et ensuite on doit appeler leur méthode equals. Deux objets peuvent avoir le même hashcode, et les deux objets ne pas être égaux. Mais deux objets ne peuvent pas être égaux, si leur hashcode est différent.
Cela permet de comparer des objets plus rapidement. La classe doit implémenter une méthode int hashCode(), qui soit la plus appropriée possible, un compromis entre la rapidité de réponse, et la capacité à être précise du point de vue égalité. Par exemple, pour deux objets Personne, on peut imaginer une méthode hashCode qui sera une fonction des deux dates de naissance, et de la première lettre du nom de famille( c'est un exemple!).
Le hashcode est utilisé notamment dans des classes comme HashTable (java.util), pour comparer les clés. Dans ces classes, il est à noter que pour toutes les clés de la hash table, le hashcode est calculé une fois pour toutes à l'insertion de la paire clé/valeur. Ce qui signifie qu'à chaque recherche de clé, il n'y a que le hashcode de la clé à rechercher, qui est à calculer.
Il ne nous reste plus ensuite qu'à le comparer avec les hash codes déjà calculés.
La performance de la méthode hashCode() est donc moins importante ici; et sa précision présente plus d'intérêt( c'est à dire diminuer le nombre d'objets ayant le même hashcode), afin de diminuer les appels à equals pour les objets ayant le même hash code.
Note: en réalité, l'implémentation des hash tables est un peu plus complexe que cela. Car on profite du hash code pour en déduire(avec une valeur absolue, puis un modulo de la taille du tableau) un index dans un tableau de listes chaînées, qui sont chacune une liste chaînée de paires clé/valeur possibles(ça limite la recherche, mais toutes n'ont pas forcément le même hash code). Mais le principe reste tout-à-fait celui qu'on a énoncé.
Revenons à la classe String.
Voici la méthode hashCode() pour les String:
/** * Returns a hash code for this string. The hash code for a * <code>String</code> object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using <code>int</code> arithmetic, where <code>s[i]</code> is the * <i>i</i>th character of the string, <code>n</code> is the length of * the string, and <code>^</code> indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; }
C'est donc une définition récursive du hashcode, écrite en itératif.
On calcule d'abord le premier hashcode, qui est le hashcode du premier caractère:
31*0 + code[premier_caract]. Puis on calcule le hashcode de la sous-chaine formée des deux premiers caractères: 31*hashcode_premier + code[deuxième_caractère] , et ainsi de suite.
RETOUR HAUT