Visão geral
StringBuilder e StringBuffer são dois conceitos facilmente confusos. Este artigo começa com o código -fonte e simplesmente analisa as semelhanças e diferenças entre os dois.
É fácil saber que um desses dois é seguro para roscas e o segura por threads é ineficiente.
Descrição em Java Doc
Java Doc é uma anotação escrita por pessoas que escrevem código -fonte. Vejamos primeiro o Doc Java.
StringBuilder
Uma sequência mutável de caracteres. Esta classe fornece uma API compatível com StringBuffer, mas sem garantia de sincronização. Esta classe foi projetada para uso como um substituto para o StringBuffer em locais onde o buffer de string estava sendo usado por um único thread (como geralmente é o caso). Sempre que possível, é recomendável que esta classe seja usada em preferência ao StringBuffer, pois será mais rápido na maioria das implementações.
As operações principais em um StringBuilder são os métodos Apêndos e Inserir, que são sobrecarregados para aceitar dados de qualquer tipo. Cada um converte efetivamente um determinado dado em uma string e depois anexa ou insere os caracteres dessa string no construtor de string. O método Apênd sempre adiciona esses caracteres no final do construtor; O método Insert adiciona os caracteres em um ponto especificado.
Por exemplo, se Z se referir a um objeto Builder de String cujo conteúdo atual é "Start", o método chama Z.Append ("LE") faria com que o construtor de cordas contenha "Startle", enquanto Z.Insert (4, "LE") alteraria o construtor de cordas para conter "Starlet".
Em geral, se os referentes SB a uma instância de um StringBuilder, então SB.Append (X) tiver o mesmo efeito que SB.Insert (sb.length (), x).
Todo construtor de cordas tem uma capacidade. Enquanto o comprimento da sequência de caracteres contido no construtor de cordas não exceder a capacidade, não é necessário alocar um novo buffer interno. Se o buffer interno transbordar, ele será aumentado automaticamente.
Instâncias do StringBuilder não são seguras para uso por vários threads. Se essa sincronização for necessária, recomenda -se que o java.lang.StringBuffer seja usado.
Salvo indicação em contrário, passar um argumento nulo para um construtor ou método nesta classe fará com que uma NullPointerException seja jogada.
Desde:
1.5
Autor:
Michael McCloskey
Veja também:
java.lang.stringbuffer
java.lang.string
StringBuffer
Uma sequência de caracteres à prova de threads e mutável. Um buffer de string é como uma string, mas pode ser modificado. Em qualquer momento, contém alguma sequência específica de caracteres, mas o comprimento e o conteúdo da sequência podem ser alterados através de determinadas chamadas de método.
Os buffers de string são seguros para uso por vários threads. Os métodos são sincronizados quando necessário, para que todas as operações em qualquer instância em particular se comportem como se ocorram em alguma ordem serial consistente com a ordem das chamadas de método feitas por cada um dos threads individuais envolvidos.
As operações principais em um StringBuffer são os métodos Apêndos e Inserir, que são sobrecarregados para aceitar dados de qualquer tipo. Cada um converte efetivamente um determinado dado em uma string e depois anexa ou insere os caracteres dessa string no buffer da string. O método Apênd sempre adiciona esses caracteres no final do buffer; O método Insert adiciona os caracteres em um ponto especificado.
Por exemplo, se Z se referir a um objeto de buffer de string cujo conteúdo atual é "Iniciar", o método chama Z.Append ("LE") faria com que o buffer de string contenha "Startle", enquanto Z.Insert (4, "LE") alteraria o buffer de cordas para conter "Starlet".
Em geral, se os referentes SB a uma instância de um StringBuffer, então sb.append (x) tiver o mesmo efeito que sb.insert (sb.length (),
Sempre que ocorre uma operação envolvendo uma sequência de origem (como anexar ou inserir a partir de uma sequência de origem), essa classe sincroniza apenas no buffer de string que executa a operação, não na fonte. Observe que, embora o StringBuffer seja projetado para ser seguro para usar simultaneamente a partir de vários threads, se o construtor ou a operação de anexar ou inserir passar uma sequência de origem que é compartilhada entre os threads, o código de chamada deve garantir que a operação tenha uma visão consistente e imutável da sequência de origem para a duração da operação. Isso pode ser satisfeito pelo chamador segurando uma fechadura durante a chamada da operação, usando uma sequência de origem imutável ou por não compartilhar a sequência de origem nos threads.
Todo buffer de string tem uma capacidade. Enquanto o comprimento da sequência de caracteres contido no buffer de string não exceder a capacidade, não é necessário alocar uma nova matriz de buffer interna. Se o buffer interno transbordar, ele será aumentado automaticamente.
Salvo indicação em contrário, passar um argumento nulo para um construtor ou método nesta classe fará com que uma NullPointerException seja jogada.
Até o lançamento do JDK 5, esta classe foi complementada com uma classe equivalente projetada para uso por um único thread, StringBuilder. A classe StringBuilder geralmente deve ser usada em preferência a esta, pois suporta todas as mesmas operações, mas é mais rápido, pois não executa a sincronização.
Desde:
JDK1.0
Autor:
Arthur van Hoff
Veja também:
java.lang.stringbuilder
java.lang.string
Resumo Javadoc
Do exposto, podemos ver:
StringBuffer e StringBuilder podem ser considerados strings variáveis.
O StringBuffer é seguro para threads e aparece primeiro e está disponível no JDK1.0.
O StringBuilder não é seguro e aparece mais tarde e só existe no JDK1.5.
As interfaces dos dois são exatamente iguais, e o StringBuilder é mais rápido.
Na verdade, é bom usá -lo normalmente, apenas conheça esses pontos, mas ainda quero ver como ele é implementado no código -fonte.
Código -fonte
Como alcançar a segurança dos threads
Você pode ver pelo código -fonte que ambos herdam uma classe abstrata AbstractStringBuilder
A classe final pública StringBuffer estende o abstringstringbuilder implementa Java.io.Serializable, a classe final da CharqueSencePublic Stringbuilder estende o abstringstringbuilder implementa java.io.Serializable, CharSequence
A quantidade de código não é muito grande, linhas de código StringBuilder440, linhas de código StringBuffer718, e o máximo é o abstringStringBuilder, com um total de 1440 linhas de código.
De várias perspectivas, analisamos o código, um é como são algumas estruturas internas importantes e a outra é como as funções que usamos geralmente são implementadas. Como a corda é imutável, ela é colocada em uma piscina constante. É acordado que o StringBuilder e o StringBuffer devem ser implementados usando uma matriz CHAR.
/*** O valor é usado para armazenamento de caracteres. */ char [] valor; /*** A contagem é o número de caracteres usados. */ int contagem;
Pode -se observar que os dados são armazenados com o valor e o comprimento é representado por uma contagem.
Vamos ver as diferentes implementações de vários métodos comuns.
StringBuffer
@Override public sincronizado StringBuffer Append (String str) {tostringcache = null; super.append (str); devolver isso; } / ** * @throws stringIndexoutOfBoundSexception {@IritDoc} * / @Override public sincronizado StringBuffer insert (int deslocamento, string str) {tostringcache = null; super.insert (deslocamento, str); devolver isso; } @Override public sincronizado string tostring () {if (tostringcache == null) {tostringcache = arrays.copyofRange (valor, 0, contagem); } retornar nova string (tostringcache, true); }StringBuilder
@Override public stringbuilder append (string str) {super.append (str); devolver isso; } / ** * @THOWS StringIndexoutOfBoundSexception {@IritDoc} * / @Override public StringBuilder Insert (Int Offset, String str) {super.insert (deslocamento, str); devolver isso; } @Override public String tostring () {// Crie uma cópia, não compartilhe a matriz Return New String (valor, 0, contagem); }Como pode ser visto no código, na maioria dos casos, o StrinbBuffer apenas adiciona uma palavra -chave sincronizada para garantir a segurança do thread. Mas o método da tostragem é diferente, então vou falar sobre isso mais tarde.
Inicializar o tamanho e como crescer
Como é na verdade uma matriz, o tamanho e o método de crescimento da matriz a partir é muito importante. Vamos dar uma olhada no código.
/** * Construa um buffer de string sem caracteres e uma capacidade inicial de 16 caracteres. */ public stringbuffer () {super (16); } /** * Construa um construtor de string sem caracteres e uma capacidade inicial de 16 caracteres. */ public stringbuilder () {super (16); }Como você pode ver, esses dois construtores padrão indicam que o tamanho da matriz padrão é 16.
Por que 16? Eu não entendi.
O que vem a seguir para se preocupar com como crescer? Vamos dar uma olhada na implementação do Append
public abstringStringBuilder Append (String str) {if (str == null) retorna appendNull (); int len = str.Length (); garantir o internal (contagem + len); str.getchars (0, len, valor, contagem); contagem += len; devolver isso; } /** * Este método possui o mesmo contrato que a segurança, mas * nunca é sincronizado. */ Void privado EnsureCapacityInternal (int MinimumCapacity) {// Código consciente de Overflow se (MinimumumCapacity - Value.Length> 0) ExpandCapacity (MinimumumCapacity); } /** * Isso implementa a semântica de expansão da segurança, sem verificação ou sincronização de tamanho *. */ void expandcapacity (int minimumcacacidade) {int newCapacity = value.length * 2 + 2; if (newCapacity - MiniMumCapacity <0) newCapacity = MinimumumCapacity; if (newCapacity <0) {if (minimumcapacidade <0) // Overflow lança novo outOfMemoryError (); newCapacity = Integer.max_value; } value = Arrays.copyof (valor, newcapacity); }Os três métodos acima explicam como expandir a capacidade.
Coloque a capacidade atual *2+2
Se o comprimento recém -adicionado for maior que esse valor, definido como o valor recém -agregado
Se estiver transbordando, jogue fora do MemoryError
Implementação de ToString em StringBuffer
/*** Um cache do último valor retornado pela tostring. Limpo * sempre que o StringBuffer for modificado. */ Char transitório privado [] ToStringCache; @Override public sincronizado StringBuffer Append (String str) {tostringcache = null; super.append (str); devolver isso; } @Override public sincronizado string tostring () {if (tostringcache == null) {tostringcache = arrays.copyofRange (valor, 0, contagem); } retornar nova string (tostringcache, true); }Como você pode ver, uma matriz ToStringCache é definida. Cada vez que os dados mudam, isso é definido como nulo. Ao fazer a tostragem, pegue -o novamente dos dados atuais.
A palavra -chave transitória é impedir que essa matriz seja serializada.
resumo
De fato, o código -fonte do próprio Java é relativamente simples. Se você pode começar com o código -fonte, poderá entender muitos princípios mais profundamente. Este artigo simplesmente lista alguns códigos de origem e explica brevemente as semelhanças e diferenças entre StringBuffer e StringBuilder. Amigos interessados podem dar uma olhada nela.
O artigo acima analisa brevemente as semelhanças e diferenças entre StringBuilder e StringBuffer da perspectiva do código -fonte (análise abrangente) é todo o conteúdo que eu compartilho com você. Espero que possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.