Prefacio
Este artículo presenta principalmente el contenido relevante sobre el análisis del código fuente JDK, StringBuilder y StringBuffer. Se comparte para su referencia y aprendizaje. No diré mucho a continuación. Echemos un vistazo a la introducción detallada juntos.
Declaración de la clase de cadena
Public Final Class String implementa Java.io.Serializable, comparable <String>, CharSequence {…}La clase de cadena usa un modificador final para indicar que no se puede heredar. Al mismo tiempo, también implementa tres interfaces, implementando la interfaz serializable para indicar que la clase de cadena puede ser serializada; La implementación de la interfaz <t> comparable proporciona principalmente un método Compareto para comparar cadenas de cadenas; También implementa la interfaz de CharSequence, que representa que Char vale una secuencia legible (Charbuffer, segmento, String, StringBuffer y StringBuilder también implementa la interfaz de CharSequence)
Caminos principales y descripciones de atributos
/*Valor de matriz de caracteres, almacenando los caracteres reales en el valor de caracteres*/privado final [];/*El valor hash del valor predeterminado de cadena 0*/private int hash; /*El valor hash del valor predeterminado de cadena 0*//*Un comparador, utilizado para clasificar los objetos de cadena, el método CompareToEignReCase utiliza*/Public Static Final Comparator <String> case_insensitive_order = new CaseInsInSitEComParator ();
Análisis de método parcial de cadena
La clase de cadena proporciona una serie de constructores, y varios de ellos ya no se recomiendan, como se muestra en la figura a continuación:
Constructor
Aquí están las implementaciones de dos constructores comúnmente utilizados:
// String str = new String ("123") public String (String original) {this.value = original.value; this.hash = original.hash;} // string str3 = new String (new Char [] {'1', '2', '3'}); public String (Char Value []) {// Copiar el valor de la matriz de caracteres para valorar this.value = Arrays.CopyOf (valor, value.length); }boolean iguales (objeto anobject)
La clase de cadena anula el método igual para comparar esta cadena con el objeto especificado. El resultado es verdadero si y solo si el parámetro no es nulo y es un objeto de cadena que representa la misma secuencia de caracteres que este objeto.
public boolean iguales (objeto anobject) {// Compare las referencias del objeto directamente y return true if (this == anobject) {return true; } // Compare la secuencia de caracteres del objeto actual con el valor de Anobject if (anobject instanceOf string) {string anotherstring = (string) anobject; int n = value.length; if (n == anotherstring.value.length) {char v1 [] = valor; char v2 [] = anotherstring.value; int i = 0; while (n--! = 0) {if (v1 [i]! = v2 [i]) return false; i ++; } return verdadero; }} return false; }int Compareto (String AnotherString)
Compare la secuencia de caracteres de dos cuerdas bit a bit. Si un poco de carácter no es el mismo, devuelva la diferencia en el valor unicode de los dos caracteres de ese bit. Todos los bits son iguales, calcule la diferencia en la longitud de las dos cadenas. Si las dos cadenas son las mismas, regrese 0.
public int Compareto (String AnothString) {int Len1 = value.length; int len2 = anotherstring.value.length; // Tome la longitud de una cadena con una longitud más pequeña int lim = Math.min (Len1, Len2); char v1 [] = valor; char v2 [] = anotherstring.value; int k = 0; while (k <lim) {// Compare el valor de secuencia de caracteres de las dos cadenas una por una. Si no es igual, devuelva la diferencia entre el unicode de los dos caracteres en esa posición char c1 = v1 [k]; char c2 = v2 [k]; if (c1! = c2) {return c1 - c2; // devuelve la diferencia entre unicode} k ++; } // Se comparan todos los bits de una cadena más pequeña, y la diferencia entre las longitudes de las dos cadenas se devuelve // Si las dos cadenas son las mismas, la diferencia entre las longitudes es 0, es decir, la misma cadena devuelve 0 return Len1 - len2; } El método CompareToignorEcase (String STR) se implementa de manera similar. El caso superior y en minúsculas de los caracteres se ignora durante la comparación, y el método de implementación es el siguiente:
public int Compare (String S1, String S2) {int n1 = s1.length (); int n2 = s2.length (); int min = math.min (n1, n2); para (int i = 0; i <min; i ++) {char c1 = s1.charat (i); char c2 = s2.charat (i); if (c1! = c2) {c1 = caracteres.touppercase (c1); C2 = carácter. if (c1! = c2) {c1 = caracteres.tolowercase (c1); C2 = carácter. Tolowercase (C2); if (c1! = c2) {// sin desbordamiento debido al retorno de la promoción numérica C1 - C2; }}}} return n1 - n2; }Native String Intern ()
Cuando se llama al método interno, si el grupo ya contiene una cadena igual a este objeto de cadena (determinado con el método igual (objeto)), se devuelve la cadena en el grupo. De lo contrario, agregue este objeto de cadena al grupo y devuelva una referencia a este objeto de cadena.
Todas las cadenas literal y las expresiones constantes de asignación de cadenas se operan utilizando el método interno, por ejemplo: String str1 = "123";
Ubicación de memoria de cadena: piscina constante o montón
Los objetos de cadena se pueden crear directamente a través de literales o a través de constructores. ¿Cuál es la diferencia?
1. Los objetos de cadena creados por cadenas literal o literal a través de el empalme "+" se almacenan en la piscina constante. Si el grupo constante existe durante la creación real, la referencia se devolverá directamente. Si no existe, se creará el objeto de cadena.
2. Cree un objeto de cadena usando el constructor y cree un objeto de cadena directamente en el montón
3. Llame al método interno, y devuelva el objeto se colocará en la piscina constante (si no existe, se colocará en la piscina constante, y si existe, se devolverá a la referencia)
El siguiente es un ejemplo de la asignación de memoria de los objetos de cadena:
Cadena str1 = nueva cadena ("123"); Cadena str2 = "123"; Cadena str3 = "123"; Cadena str4 = str1.intern (); System.out.println (str1 == str2); // False Str1 crea un objeto en el montón, Str2 crea un objeto en el sistema constante del sistema.out.println (str2 == str3); // True Str2 crea un objeto en el grupo constante, STR3 devuelve directamente una referencia al objeto creado por Str2, por lo que Str2 y Str3 apuntan al mismo objeto en el grupo constante System.out.println (str4 == Str3); // Verdadero Str4 Devuelve un objeto con un valor de "123" en el grupo constante, por lo que Str4, Str2 y Str3 son iguales.Acerca de un ejemplo de costura de cadena:
public class StringTest {public static static final String x = "ABC"; // constante x @test public void test () {String str5 = new String ("ABC"); Cadena str6 = str5+"def"; // Crear cadena str7 = "ABC"+"def"; // cadena constante de la piscina str8 = x+"def"; // x es una constante, y el valor es fijo, por lo que el valor de x+"def" se ha establecido en ABCDEF. De hecho, después de la compilación, el código es equivalente a String str8 = "ABCDEF" String str9 = "ABC"; Cadena str10 = str9+"def"; //System.out.println(str6==str7); // falso sistema.out.println (str8 == str7); // True System.out.println (str10 == str7); // falso sistema.out.println (x == str9); //verdadero} }El código descompilado será claro de un vistazo:
La asignación de memoria es la siguiente:
String, StringBuffer, StringBuilder
Dado que la matriz de caracteres del valor de la propiedad [] para almacenar cadenas mantenidas internamente por tipo de cadena se modifica con final:
/** El valor se utiliza para el almacenamiento de personajes. */Valor de char Final privado [];
Indica que se puede modificar después de la asignación. Por lo tanto, creemos que el objeto de cadena es inmutable una vez creado. Si encuentra operaciones frecuentes de cadena de empalme durante el desarrollo, si usa el contacto proporcionado por la cadena o usa la cadena de empalme "+" directamente, se generarán nuevas cadenas con frecuencia, lo que será ineficiente. Java proporciona otras dos clases: StringBuffer y StringBuilder, que se utilizan para resolver este problema:
Eche un vistazo al siguiente código:
Cadena str1 = "123"; Cadena str2 = "456"; Cadena str3 = "789"; Cadena str4 = "123" + "456" + "789"; // Agregar constantes, el compilador reconoce automáticamente la cadena Str4 = "123456789" String Str5 = Str1 + Str2 + Str3; // STAND STRING String Variable Splacting, se recomienda usar StringBuilder StringBuilder sb = new StringBuilder (); sb.append (str1); sb.append (str2); sb.append (str3);
La siguiente es la implementación de la clase StringBuilder, que solo intercepta parte del código analizado:
public Final Class StringBuilder extiende AbstractStringBuilder implementos java.io.serializables, charshiele {// divide string @override public stringBuilder append (string str) {// llamando a la clase matriz abstringbuilder.append super.append (str); devolver esto; }} Abstract Class AbstractStringBuilder implementos APEENTABLE, CharSequence { / *** La matriz de caracteres que almacena cadenas, tipo no final, diferente de la clase de cadena* / char [] valor; /*** El recuento es el número de caracteres utilizados. */ int count; public AbstractStringBuilder append (String Str) {if (str == null) return appendNull (); int len = str.length (); // verifique si la capacidad debe ampliarse a EnsurecapacityInternal (recuento + len); // Copiar la cadena str a valor str.getChars (0, len, valor, contar); recuento += len; return this;} private void seturecapacityInternal (int mínimoCapacity) {// Overflow -Conscious Code // MinimumCapacity = Count+Str.length // Si la capacidad después de STR está empalmada es mayor que la capacidad de valor, expandir si (MinimumCapacity - Value.length> 0) {// expandir la capacidad, y copiar el valor de valor actual a la expansión del carácter de la expansión, el valor de referencia, el valor de la referencia de retorno, el valor de la referencia. Arrays.copyOf (valor, newcapacity (mínimo de capacidad)); }} // stringBuilder expansión privada int newCapacity (int mincapacity) {// Overflow-conscious Code // Calcule la capacidad de expansión // La longitud de matriz de expansión predeterminada se expande 2 veces la longitud del grupo de número (valor []) original y luego 2 se agregan a la regla. ¿Por qué agregar 2? int newCapacity = (value.length << 1) + 2; if (newCapacity - mincapacity <0) {newCapacity = mincapacity; } return (newCapacity <= 0 || max_array_size - NewCapacity <0)? HugeCapacity (mincapacity): newcapacity; }}Lo mismo es cierto para StringBuffer y StringBuilder. La matriz de caracteres de valor [] mantenida internamente es mutable. La única diferencia es que StringBuffer es seguro de hilo. Sincroniza todos los métodos. StringBuilder es hilo, no seguro. Por lo tanto, cuando se prefiere las variables de operación de múltiples subprocesos y de intercambio, se prefiere StringBuffer para el procesamiento de empalme de cadenas. De lo contrario, se puede usar StringBuilder. Después de todo, la sincronización de hilos también traerá cierto consumo.
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.