Prefácio
Este artigo apresenta principalmente o conteúdo relevante sobre a análise de código -fonte do JDK, StringBuilder e StringBuffer. É compartilhado para sua referência e aprendizado. Não vou dizer muito abaixo. Vamos dar uma olhada na introdução detalhada juntos.
Declaração da classe String
Classe final public final String implementa Java.io.Serializable, comparável <string>, Charsequence {…}A classe String usa um modificador final para indicar que não pode ser herdado. Ao mesmo tempo, também implementa três interfaces, implementando a interface serializável para indicar que a classe String pode ser serializada; A implementação da interface <T> comparável fornece principalmente um método compareto para comparar strings de strings; Também implementa a interface Charsequence, que representa que Char vale uma sequência legível (CharBuffer, Segment, String, StringBuffer e Stringbuilder também implementa a interface Charsequence)
Campos principais da string e descrições de atributos
/*Valor da matriz de caracteres, armazenando os caracteres reais na string*/private final Char Value [];/*O valor de hash do valor padrão da string 0*/private int hash; /*O valor de hash do valor padrão da string 0*//*um comparador, usado para classificar objetos de string, o método comparetoignorecase usa*/public estático comparador final <string> case_insensitive_order = new caseinsensitivecomParator ();
Análise de método parcial da sequência
A classe String fornece uma série de construtores, e vários deles não são mais recomendados, conforme mostrado na figura abaixo:
Construtor
Aqui estão as implementações de dois construtores comumente usados:
// 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 []) {// copie o valor da matriz do caractere para valor }BOOLEAN é igual (objeto anobject)
A classe String substitui o método igual para comparar essa string com o objeto especificado. O resultado é verdadeiro se e somente se o parâmetro não for nulo e for um objeto String que representa a mesma sequência de caracteres que este objeto.
public boolean é igual (objeto anobject) {// compare o objeto referencia diretamente e retorne true se (this == AnoBject) {return true; } // Compare a sequência do caractere do objeto atual com o valor anobject if (anobject instanceof string) {string anototherstring = (string) anobject; int n = value.length; if (n == anotherstring.value.length) {char v1 [] = value; char v2 [] = anototherstring.value; int i = 0; while (n--! = 0) {if (v1 [i]! = v2 [i]) retorna false; i ++; } retornar true; }} retornar false; }int compare (string anotherstring)
Compare a sequência do personagem de duas cordas pouco a pouco. Se um caractere um pouco não for o mesmo, retorne a diferença no valor Unicode dos dois caracteres desse bit. Todos os bits são iguais, calcule a diferença no comprimento das duas cordas. Se as duas cordas forem iguais, retorne 0.
public int compareto (string anotherstring) {int len1 = value.length; int len2 = anototherstring.value.length; // Tome o comprimento de uma corda com um comprimento menor int lim = math.min (len1, len2); char v1 [] = value; char v2 [] = anototherstring.value; int k = 0; while (k <lim) {// compare o valor da sequência do caractere das duas strings uma a uma. Se não for igual, retorne a diferença entre o unicode dos dois caracteres nessa posição char c1 = v1 [k]; char c2 = v2 [k]; if (c1! = c2) {return c1 - c2; // retorna a diferença entre unicode} k ++; } // Todos os bits de uma corda menor são comparados, e a diferença entre os comprimentos das duas cordas é retornada // se as duas cordas forem iguais, a diferença entre os comprimentos é 0, ou seja, a mesma string retorna 0 retornar Len1 - Len2; } O método comparetoignorecase (string str) é implementado da mesma forma. O caso superior e inferior dos caracteres é ignorado durante a comparação, e o método de implementação é o seguinte:
public int compare (string s1, string s2) {int n1 = s1.length (); int n2 = s2.length (); int min = math.min (n1, n2); for (int i = 0; i <min; i ++) {char c1 = s1.charat (i); char c2 = s2.Charat (i); if (c1! = c2) {c1 = caractere.TOUPPERCASE (C1); c2 = caractere.TOUPPERCASE (C2); if (c1! = c2) {c1 = caractere.tolowercase (c1); c2 = caractere.TolowerCase (C2); if (c1! = c2) {// sem transbordamento por causa do retorno da promoção numérica C1 - C2; }}}} retornar n1 - n2; }Native String Intern ()
Quando o método do Intern é chamado, se o pool já contiver uma string igual a esse objeto String (determinado com o método igual (objeto)), a sequência no pool será retornada. Caso contrário, adicione este objeto String ao pool e retorne uma referência a este objeto String.
Todas as cordas literais e expressões constantes de atribuição de string são operadas usando o método estagiário, por exemplo: string str1 = "123";
Local de memória da string: pool ou pilha constante
Objetos da string podem ser criados diretamente através de literais ou através de construtores. Qual é a diferença?
1. Objetos de cordas criados por seqüências literais ou literais através do splicing "+" são armazenadas no pool constante. Se o pool constante existir durante a criação real, a referência será retornada diretamente. Se não existir, o objeto String será criado.
2. Crie um objeto String usando o construtor e crie um objeto de string diretamente na pilha
3. Chame o método do estagiário e retorne o objeto será colocado no pool constante (se não existir, ele será colocado no pool constante e, se existir, será devolvido à referência)
A seguir, é apresentado um exemplo da alocação de memória de objetos de string:
String str1 = new string ("123"); String str2 = "123"; String str3 = "123"; String str4 = str1.intern (); System.out.println (str1 == str2); // false str1 cria um objeto no heap, o str2 cria um objeto no sistema de pool constante.out.println (str2 == str3); // true str2 cria um objeto no pool constante, o STR3 retorna diretamente uma referência ao objeto criado pelo STR2, então o STR2 e o STR3 apontam para o mesmo objeto no sistema de pool constante.out.println (str4 == str3); // true str4 retorna um objeto com um valor de "123" no pool constante; portanto, STR4, STR2 e STR3 são iguais.Sobre o exemplo de costura de cordas:
classe pública stringtest {public static final string x = "abc"; // constante x @test public void test () {string str5 = new string ("abc"); String str6 = str5+"def"; // crie string str7 = "abc"+"def"; // string constante do pool str8 = x+"def"; // x é uma constante e o valor é fixo, portanto o valor de x+"def" foi definido como ABCDEF. De fato, após a compilação, o código é equivalente a string str8 = "abcdef" string str9 = "abc"; String str10 = str9+"def"; //System.out.println(str6=str7); // false System.out.println (str8 == str7); // true system.out.println (str10 == str7); // false System.out.println (x == str9); //verdadeiro} }O código descompilado ficará claro rapidamente:
A alocação de memória é a seguinte:
String, StringBuffer, StringBuilder
Como o valor da propriedade [] matriz de caracteres para armazenar strings mantidos internamente pelo tipo de string é modificado com final:
/** O valor é usado para armazenamento de caracteres. */Valor de char final privado [];
Indica que pode ser modificado após a atribuição. Portanto, acreditamos que o objeto String é imutável uma vez criado. Se você encontrar operações frequentes de strings de splicing durante o desenvolvimento, se você usar o contato fornecido por string ou usar a string de splicing "+" diretamente, novas seqüências serão geradas com frequência, o que será ineficiente. Java oferece outras duas classes: StringBuffer e StringBuilder, que são usadas para resolver esse problema:
Dê uma olhada no seguinte código:
String str1 = "123"; String str2 = "456"; String str3 = "789"; String str4 = "123" + "456" + "789"; // Adicionar constantes, o compilador reconhece automaticamente a string str4 = "123456789" String str5 = str1 + str2 + str3; // Stand String Variable Splicing, é recomendável usar StringBuilder StringBuilder SB = new StringBuilder (); sb.append (str1); sb.append (str2); sb.append (STR3);
A seguir, é apresentada a implementação da classe StringBuilder, que intercepta apenas parte do código analisado:
A classe final public StringBuilder estende o abstringStringBuilder implementa java.io.Serializable, Charsequence {// dividir String @Override public StringBuilder Append (String str) {// chamando a classe pai abstringStringBuilder.append Super.append (str); devolver isso; }} Resumo Classe AbstractStringBuilder implementa anexos, Charsequence { / *** A matriz de caracteres que armazena strings, tipo não final, diferente do valor da classe String* / char []; /*** A contagem é o número de caracteres usados. */ int contagem; public abstringStringBuilder Append (String str) {if (str == null) retorna appendNull (); int len = str.Length (); // Verifique se a capacidade precisa ser expandida para garantir a capacidade de capacidade (contagem + len); // copie a string str para valorizar str.getchars (0, len, valor, contagem); contagem += len; return this;} private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code // minimumCapacity=count+str.length // If the capacity after str is spliced is greater than the value capacity, expand if (minimumCapacity - value.length > 0) { //Expand capacity, and copy the current value value to the expanded character array, return the new array reference value = Arrays.copyof (Valor, NewCapacity (MinimumumCacacidade)); }} // StringBuilder Expansion Private int NewCapacity (int MinCapacity) {// Código consciente de Overflow // Calcule a capacidade de expansão // O comprimento da matriz de expansão padrão é expandido em 2 vezes o número de grupo original (valor []) e, em seguida, 2 são adicionados à regra. Por que adicionar 2? int newCapacity = (value.length << 1) + 2; if (newCapacity - MinCapacity <0) {newCapacity = mincapacity; } return (newCapacity <= 0 || max_array_size - newCapacity <0)? HugeCapacity (Mincapacidade): NewCapacity; }}O mesmo vale para StringBuffer e StringBuilder. A matriz de caracteres do valor [] mantida internamente é mutável. A única diferença é que o StringBuffer é seguro para threads. Ele sincroniza todos os métodos. StringBuilder é thread-não é seguro. Portanto, quando a operação multitreada e o compartilhamento de variáveis de string, o StringBuffer é preferido para o processamento de splicing de string. Caso contrário, o StringBuilder pode ser usado. Afinal, a sincronização do thread também trará certo consumo.
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.