[JAVA] J'ai lu la source de String

D'une manière ou d'une autre, j'ai décidé de lire également la source JDK. Cela dit, je n'ai pas le temps de lire attentivement chaque ligne, alors je l'ai lu brièvement et j'ai trouvé ce code. La dernière fois j'ai lu la source de Long, c'est donc String.

Classe de chaîne

La classe String est une classe de chaîne. Depuis que nous avons créé Byte, Short, Integer et Long, on peut dire que String est également une classe wrapper pour char []. Eh bien, le terrain.

String.java


    private final char value[];
    private int hash; // Default to 0
    public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();

Il y a char [] qui est le corps de la chaîne. hash est attribué uniquement dans le constructeur suivant. Sinon, il reste 0.

String.java


    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

Calculé lorsque la longueur de la chaîne est supérieure à 0 et que le hachage est égal à 0 lorsque la méthode hashCode est appelée. Lorsque la valeur de hachage calculée par hasard est 0, je pense qu'elle ne devrait pas être calculée à chaque fois, mais c'est peu probable.

String.java


    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

Il y avait une constante appelée CASE_INSENSITIVE_ORDER. Je me suis demandé si c'était possible récemment, mais c'était à partir du JDK 1.2.

méthode length, méthode isEmpty

La méthode length renvoie la longueur. C-like strlen recherche jusqu'à NULL caractères à chaque fois, mais java ne renvoie que la taille du tableau. Cela signifie que la valeur garantit la taille parfaite. Eh bien, c'est immuable, vous n'avez donc pas besoin de marge.

String.java


    public int length() {
        return value.length;
    }

IsEmpty a été ajouté depuis JDK 1.6.

String.java


    public boolean isEmpty() {
        return value.length == 0;
    }

Le contenu est le même que length () == 0, mais c'est une méthode très java qui peut être jugée par le type booléen sans comparer la magnitude de la valeur numérique.

méthode charAt, méthode toCharArray

charAt est une méthode pour obtenir un caractère à la fois, et toCharArray est une méthode pour obtenir un lot de tableaux.

String.java


    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

    public char[] toCharArray() {
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }

charAt ne récupère les éléments qu'en indexant le tableau, mais toCharArray sécurise un autre tableau de la même taille et le copie. Sauf raison particulière, il est préférable d'accéder avec charAt en se tournant vers length () avec l'instruction for.

Au fait, j'ai vu dans les sources d'autres personnes que vous pouvez le diviser en une seule chaîne de caractères avec str.split ("");, mais arrêtez-le comme ceci. Cela signifie que vous pouvez créer des instances String uniquement pour les types de caractères contenus dans la chaîne.

méthode interne, méthode égale

Il existe une méthode interne. Pour être honnête, j'aimerais que vous arrêtiez de faire ça. L'implémentation est une méthode native. J'ai l'impression de faire la valeur de référence en interne.

String.java


    public native String intern();

Comment utiliser stag ...

Main.java


    public static void main(String[] args) {
        String s01 = "abc";
        String s02 = "abcdef".substring(0, 3);
        System.out.println(s01 == s02);
        System.out.println(s01.equals(s02));
        String s03 = s02.intern();
        System.out.println(s01 == s03);
        System.out.println(s01.equals(s03));
    }

Quand tu cours ...

false
true
true
true

La valeur de référence est différente lorsque la sous-chaîne est utilisée, mais la valeur de référence est la même lorsque intern est utilisé.

Voici la méthode égale,

String.java


    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Faites attention à ceci == anObject au début. Plutôt que d'écrire toujours l'opérateur de comparaison == en partant du principe que tout est interne, si vous l'écrivez en égal pour le moment, ce sera plus rapide s'il est interne et de la même instance.

Avec égal, la boucle est interrompue à différents points lorsque les longueurs de chaîne sont différentes ou comparées depuis le début, mais le traitement est appliqué lorsque le dernier caractère est différent ou la même chaîne. C'est donc le plus rapide à comparer par valeur de référence, mais d'une manière ou d'une autre, il semble efficace de renvoyer false s'il ne correspond pas en comparant avec hashCode après avoir comparé la longueur. Si hashCode n'est pas calculé, il bouclera jusqu'à 2 fois.

indexOf, méthode

indexOf existe depuis longtemps, mais si vous vous demandez pourquoi l'argument est int ch ...

String.java


    public int indexOf(int ch, int fromIndex) {
        final int max = value.length;
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }

        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }

    private int indexOfSupplementary(int ch, int fromIndex) {
        if (Character.isValidCodePoint(ch)) {
            final char[] value = this.value;
            final char hi = Character.highSurrogate(ch);
            final char lo = Character.lowSurrogate(ch);
            final int max = value.length - 1;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == hi && value[i + 1] == lo) {
                    return i;
                }
            }
        }
        return -1;
    }

Oh, supportait-il les paires de substitution? L'indexOfSupplementary recherche chacun des deux caractères, mais la première moitié est U + D800 à U + DBFF et la seconde moitié est U + DC00 à U + DFFF.

Recherchez simplement lastIndexOf à l'arrière et il existe une méthode pour les paires de substitution appelée lastIndexOfSupplementary. Il semble que JDK 1.5 soit compatible avec les paires de substitution. Il n'y avait pas de MIN_SUPPLEMENTARY_CODE_POINT dans la source du JDK 1.4. Depuis JDK 1.4, l'argument de indexOf est int ch. Ce genre de chose est incroyable.

méthode toString

Je ne sais pas s'il y a des gens dans le monde qui écrivent "abc" .toString () ...

String.java


    public String toString() {
        return this;
    }

Revenez.

finalement

Je ne sais pas si la classe String est une bibliothèque d'exécution ou une partie d'une spécification de langage. Par exemple, le constructeur par défaut est ...

String.java


    public String() {
        this.value = "".value;
    }

Recommended Posts

J'ai lu la source de String
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
J'ai lu la source de Long
J'ai lu la source de Short
J'ai lu la source de Byte
J'ai lu le livre de démarrage de Kotlin
DrainTo de LinkedBlockingQueue est-il sûr? J'ai suivi la source
Diverses méthodes de la classe String
J'ai essayé de résumer les méthodes de Java String et StringBuilder
J'ai étudié le traitement interne de Retrofit
Point 63: Méfiez-vous des performances de la concaténation de chaînes
Je vais absolument convertir la chaîne de temps!
L'histoire de la comparaison de chaînes de bas niveau en Java
J'ai vérifié la partie de java.net.URL # getPath
J'ai compris les bases de la saisie de caractères
[Java] Obtenir la longueur de la chaîne de paire de substitution
[Java] La partie déroutante de String et StringBuilder
J'ai comparé les caractéristiques de Java et .NET
Je veux var_dump le contenu de l'intention
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
J'ai vérifié le nombre de taxis avec Ruby
Essayez Progate Free Edition [Java I]
Comparaison de chaînes de caractères: j'ai été pris dans le problème de vérification des compétences de Paisa
[Java] Comment obtenir l'URL de la source de transition
J'ai examiné le cycle de vie de l'extension de JUnit Jupiter
Le monde de Clara-Rules (2)
J'ai essayé d'utiliser la fonction Server Push de Servlet 4.0
J'ai lu le code lisible, alors prends note
J'étais accro au record du modèle associé
J'ai essayé de réduire la capacité de Spring Boot
J'ai essayé le nouveau profileur de fonctionnalités d'IntelliJ IDEA 2019.2.
Le monde de Clara-Rules (4)
Traitement d'image: structure de base de l'image lue par le programme
Je souhaite afficher le nom de l'affiche du commentaire
J'ai résumé le format d'affichage de la réponse JSON de Rails
Le monde de Clara-Rules (1)
Lire la source Java HashMap
J'ai lu le "Guide pratique orienté objet", donc un mémorandum
Source des objets cellulaires
Relisez le guide des rails (vue d'ensemble du contrôleur d'action)
[Java] Lors de l'écriture du source ... Mémorandum ①
J'ai écrit un diagramme de séquence de l'exemple j.u.c.Flow
Le monde de Clara-Rules (5)
J'ai résumé les types et les bases des exceptions Java
L'idée du tri rapide
Je suis parfaitement conscient de la commodité de graphql-code-generator partie 2
Je ne peux pas sortir de l'écran de la console Rails db
Je veux retourner la position de défilement de UITableView!
L'idée de jQuery
J'ai créé le côté serveur du jeu de cartes en ligne ①
À propos de la troncature de String par le nombre d'octets sur Android
J'ai essayé de résumer les bases de kotlin et java
Mettez le fichier dans les propriétés de string avec la configuration spring xml