String, StringBuiler e StringBuffer
Autor: Gustavo | Publicado: 2015-04-13T09:00:00-03:00






&nbsp; &nbsp; Este mês de abril comecarei fazendo
algo que sempre tive vontade de fazer mas nunca houve disciplina o
suficiente. Irei fazer o post em português e em inglês. A idéia é
não somente praticar a disciplina de estudar tecnologia como
praticar um pouco de inglês uma vez que morando no Brasil a prática
da língua fica um pouco complicada.

&nbsp; &nbsp;&nbsp;No fim deste mês pretendo ter
percorrido as principais postagens e quem sabe até todas caso veja
necessidade com melhores abordagens em português e com sua
respectiva tradução em inglês. Comecarei falando hoje sobre
String, StringBuilder e StringBuffer espero que gostem... críticas
sugestões são bem vindos.



String, StringBuilder e StringBuffer



&nbsp; &nbsp;&nbsp;A primeira coisa que você deverá
aprender quanto a String é que ela é imutável, por mais que você
altere o valor dela, o que na verdade foi alterado foi a sua
referência mas o valor e a instância continuam a mesma. Vamos
desenvolver mais isto:

&nbsp; &nbsp;&nbsp;Vamos comecar pela declaração de
uma String. Por ser um objeto assim como tudo em java, ela poderá
ser declarada de várias formas, isto porque possuem seu contrutor
sobrecarregado de várias formas conforme podermo ver na figura 1
abaixo:









Figura-1



&nbsp; &nbsp;&nbsp;Mas apesar de possuir vários
construtores, os mais comuns utilizados, pelo menos pela minha
experiência de mercado são:



  String
var
= new
String();

  String
var1
= new
String("Let's
Surf!");



&nbsp; &nbsp;&nbsp;Entretanto existem formas mais usuais
de se declarar uma variável String conforme abaixo:



  String
var
= "";

  String
var1
= "Let's
Surf!";



&nbsp; &nbsp;&nbsp;Conforme já dissemos antes, ao
declararmos um objeto String, ele nunca mais irá deixar de ter
aquele valor o que é possível fazer é direcionar a variável para
uma outra instância que essa sim aponta para outro valor que foi
desejado isso quer dizer que  se fizermos:



 String
var
= "
";

 var
= "Let's
Surf!";



&nbsp; &nbsp;&nbsp;Podemos
dizer que o código acima cria dois objetos string, o primeiro possui
um caractere de espaço, já o segundo
é um a outro objeto string criado com o valor Let's Surf! que
por sua vez é referenciado a variável var.
Quanto ao objeto anterior, ele ficou perdido sem ter nenhuma
variável a referenciado até o heap.
Explicando com imagens podemos dizer que o que aconteceu foi:





&nbsp; &nbsp;&nbsp;Nesta
figura o quadrado representaria a pilha que tem uma variável “var”
declarada em uma nuvem que seria a memória heap, com seus círculos
que seria a memória ocupada pelo texto. Já a seta que vai do
retângulo a circunferência é a referência que tanto falamos
apontando da variável ao conteúdo da memória heap. 


&nbsp; &nbsp;&nbsp;Comparado
com a imagem abaixo, veremos que as imagens irão ser bem parecidas,
a diferença é que a referência entre a variável “var” e a
memória heap declarada anteriormente foi perdida, entrando em seu
lugar  a referência a uma nova memória com o valor de “Let's
Surf!”. Quanto a antiga referência não existe mais, nesta imagem
colocarei uma seta tracejada como forma de orientação mas não
pense que por haver uma seta tracejada faz de ser possível de alguma
forma voltar a referência a esta memória do heap, se por acaso eu 
sobrescrevesse o valor da variável de “Let's Surf” para “ ”
de novo um novo objetos seria criado e este continuaria solto no
Heap.





&nbsp; &nbsp;&nbsp;Aprofundando
um pouco mais, sobre atribuição de valores a objetos String, é
muito importante nos atentarmos por exemplo veja o código abaixo:



  String
var1
= new
String("Let's
Surf");



  String
var2
= "
In Rio";
//
atribuindo
valor in Rio a variavel var2

  System.out.println(var2);
//
imprime:
In Rio

  var2
= var1+var2;//atribuição
do valor de var1+var2 a var2 novamente

  System.out.println(var2);//
Let's
Surf In Rio

  var2.concat("
Baby!");//
altera
mas não passa o valor a referência

  System.out.println(var2);//
logo
imprime valor: Let's Surf In Rio

  var2
= var2.concat("!");//
agora
sim temos a referência

  System.out.println(var2.toUpperCase());//não
temos  referê

  var2.toUpperCase();

  System.out.println(var2);//
como
o valor não atribuiu a variável        //nada ocorre

  

Saida:

 In
Rio

Let's
Surf In Rio

Let's
Surf In Rio

LET'S
SURF IN RIO!

Let's
Surf In Rio!



&nbsp; &nbsp;&nbsp;Saberia
me dizer quantos objetos foram criados no código acima?

Então
veja novamente e tente responder, depois continue a leitura:

&nbsp; &nbsp;&nbsp;Comecamos
com a instanciação do  primeiro objeto e referenciando-o a var1,
o  mesmo ocorre de forma idêntica para a JVM durante a declaração
e referenciação a var2. Após imprimir a variável var2,
temos na quarta linha algo um pouco diferente, estamos fazendo uma
junção dos valores de var1 e var2, criando assim um
novo objeto e atribuido este novo objeto a var2. Neste caso o
objeto antigo que referenciava a var2 ficará perdido
alterando também o valor de var2.





&nbsp; &nbsp;&nbsp;Seguindo
adiante no código, vemos que var2 chama o método concat
da classe String mas, mesmo atibuindo o valor “Baby!”” ao
método, este objeto criado não é referenciado a variável var2,
desta forma o valor não
será atribuido a var2
deixando nosso heap da seguinte forma:





&nbsp; &nbsp;&nbsp;Em
seguinda vemos uma nova chamada ao método concat
mas desta vez além da criação de um novo objeto String com o
caracter de exclamação no final da frase, é feita a referência a
variável var2,
é possível confirmar chamando para imprimir novamente a variável e
vemos seu resultado conforme esperado.

&nbsp; &nbsp;&nbsp;Quanto
as três últimas linhas, foram deixadas para demonstrar que o valor
do texto é alterado com a
criação de um novo objeto, mas
não referenciado a variável, com isso chamamos duas vezes o método
toUpperCase
uma dentro do println
e outra fora e
chamarmos novamente a impressão da variável var2
e vermos que ela não foi alterada e
que nosso código resultou na criação de sete objetos confrome
imagem abaixo pode achar estranho mas o motivo de terem sido criada
sete e não seis objetos String foi pelo método toUpperCase
da classe String ter sido chamado duas vezes:





&nbsp; &nbsp;&nbsp;Em
geral se você entendeu bem isto, terá entendido grande parte da
complexidade da classe String só temos mais duas coisas a
acrescentar que são os únicos momentos em que um objetos String não
é criado:


Ao
 referenciar uma variável a outra assim como objetos;


Ao
 atribuir um texto de forma literal um texto já existente no heap de
 forma idêntica;





&nbsp; &nbsp;&nbsp;O
primeiro caso não novidade por motivos de qualquer objeto ter o
mesmo comportamento isso quer dizer que:



 
String
 var3
 = "um";

String
 var4
 = var3;//
 referenciando
 a um
 mesmo
 objeto




&nbsp; &nbsp;&nbsp;Já
o segundo caso caso é por uma questão de economia de memória feita
pela própria JVM. Em caso de atribuir um texto de forma literal a
uma variável, não será criado um novo objeto ex:



String
var5
= "LET'S
SURF IN RIO";//já
existe
no heap

String
var6
= "Let's
surf in Rio Baby!";//já
existe
no heap

String
var7
= "Let's
surf in Rio";//já
existe
no heap

String
var8
= "Let's
surf in Rio";//já
existe
no heap

String
var9
= new
String("Let's
surf in Rio");//
a chamada
de
new forca
a criacao
de
um
novo
objeto

String
var10
= var9.toLowerCase();
//
a chamada
por
meio
de
um
método,
faz
com
que
chame
a palavra
reservada
new 



Métodos
String



&nbsp; &nbsp;A
classe String tem vários métodos que poderão ser
utilizados para facilitar seu dia-dia.&nbsp;&nbsp; &nbsp;&nbsp;É
sempre válido acessar a documentação
da oracle para saber detalhes da utilização
dos métodos além de ver exemplos.

 Irei
mencionar aqui apenas os principais mas fique a vontade em pesquisar
por novos métodos.




CharAt(
 )
 -  Irá retornar o character localizado no índice informado.String
 aux
 = "0123456789";System.out.println("aux.charAt(5)
 = "+aux.charAt(5));Saida:
 aux.charAt(5)
 = 5


Concat()=
 Adiciona um texto literal ou por meio de variável ao final assim
 como a utilização do sinal de mais (+).String
 aux
 = "0123456789
 ";aux
 += aux.concat(aux);System.out.println("aux
 = "+aux);Saida:
 aux
 = 0123456789 0123456789 0123456789


toUpperCase:Cria
 uma nova String com todos seus caracteres maiúsculos.String
 aux
 =
 "testMyString";System.out.println(aux.toUpperCase());Saida:TESTMYSTRING


toLowerCase:Cria
 uma nova String com todos seus caracteres minúsculos.String
 aux
 =
 "testMyString";System.out.println(aux.toLowerCase());Saida:testmystring


equalsIgnoreCase(
 )
 Valida
 a igualdade
 entre dois valores strings. desconsiderando maiúsculo ou
 minúsculo.String
 aux
 =
 "testMyString";System.out.println(aux.toLowerCase().equalsIgnoreCase(aux.toUpperCase()));

Saida:true


length():
 Mede o número de caracteres que
 uma string possui.String
 aux
 = "01234";System.out.println(aux.length());Saida:5


replace(oldChar,newChar)
 : Substitui os caractere contido no oldChar substituindo para o novo
 char.String
 aux
 = "testMyString";System.out.println(aux.replace("t","X"));

Saida:
 XesXMySXring


trim()
 :
 Remove os caracteres de espaco do início e fim de um texto.

aux
 = "
 test My String
 ";System.out.println("*"+aux+"*");System.out.println("*"+aux.trim()+"*")

Saida:*
 test My String **test My String*





StringBuffer
e StringBuilder



&nbsp; &nbsp;&nbsp;As
classes StringBuffer e StringBuilder são muito semelhantes, possuem
os mesmos métodos para desenvolvimento e são utilizadas para que,
ao necessitar da alteração frequente de caracteres de uma String
não gere novos objetos Strings sobrecarregando o pool de memória,
aderindo assim uma dessas classes que realizam o trbalho sem o
sobreccaregamento do pool e com melhores ferramentas para manuseio ao
texto.

&nbsp; &nbsp;&nbsp;Apesar
das semelhanças é claro que elas possuem também algumas diferenças
caso contrário não teria sentido nenhum termos duas classes
idênticas em uma API. A classe StringBuilder não é sincronizada
isso significa que ela não é preparada para trabalhar em um
ambiente onde haverá processamentos simultâneos. Por conta disto
ela também executa com mais velocidade que a StringBuffer, que
apesar de ser sincronizada, a própria ORACLE
sugere que utilize a StringBuilder e no caso de necessiade de
realizar I sincronismo, que o facamos manualmente ao invés de
utilizarmos dos métodos  da API.

&nbsp; &nbsp;&nbsp;Diferente
de quando utilizamos texto  com objetos String, ao utiliizarmos
StringBuffer e StringBuilder não é necessário estarmos
referenciando a nossa variável o tempo todo vejamos alguns exemplos:



  String
 testString
= "surfing";

  StringBuilder
 testStringBuilder
= new
StringBuilder("surfing");

  StringBuffer
 testStringBuffer
= new
StringBuffer("surfing");

  testString.concat("
in Rio!");

  testStringBuffer.append("
in Rio!");

  testStringBuilder.append("
in Rio!");

  System.out.println("testString
= "+testString);

  System.out.println("testStringBuffer
= "+testStringBuffer);

  System.out.println("testStringBuilder
= "+testStringBuilder);

  testString
= testString.concat("
in Rio!");

  System.out.println("&gt;&gt;
testString = "+testString);



Saida:

testString
= surfing

testStringBuffer
= surfing in Rio!

testStringBuilder
= surfing in Rio!

&gt;&gt;
testString = surfing in Rio!



 Vemos
que tanto StringBuilder quanto StringBuffer não necessitam de uma
referência a sua nova variável conforme vimos antes.



Construtores
StringBuffer e StringBuilder



&nbsp; &nbsp;&nbsp;Construtores
como já devemos saber são as formas que utilizamos para instanciar
um objeto, o StringBuffer e o StringBuilder possuem os mesmos
construtores então ao ver a descrição do StringBuilder, tenha como
certo que o mesmo ocorre para StringBuffer:




StringBuilder():Construtor
 padrão que reserva uma capacidade de 16 caracteres para serem
 armazenados.


StringBuilder(charSeq
 c):Construtor
 que realiza
 a leitura do charSeq  que reserva
 uma capacidade de 16 caracteres mais
 o tamanho do charSeq afime de ser armazenado.


StringBuilder(int
 capacity):Construtor
 que realiza
 a leitura do
 inteiro que se refere a capacidade
 para
 armazenar caracteres, caso coloque uum valor negativo terá como
 resposta uma exceção NegativeArraySizeException.


StringBuilder(String
 str):Construtor
 que realiza
 a leitura da
 string
 str que
 reserva
 uma capacidade de 16 caracteres mais
 o tamanho do texto
 passado  como parâmetro.







Métodos
StringBuffer e StringBuilder



&nbsp; &nbsp;&nbsp;Citarei
aqui os métodos mais conhecidos e utilizados que devemos saber para
a utilização de um objeto, o StringBuffer e o StringBuilder. Assim
como anterioemente amobs possuem os mesmos métodos então ao ver a
descrição do StringBuilder, tenha como certo que o mesmo ocorre
para StringBuffer e vice-versa:




append(String
 s): Conforme
 já demonstrado, append é um método que insere caracteres ao final
 do texto da variáve. Ele tem vários sobrecarregamentos aceitando
 booleanos, chars, Strings, Array dentre outros.




delete(int
 start, int end):Este
 métdo  possui dois sobrecarregamentos. Um
 onde é possível informar o intervalo da string que será
 removido
 e outro conforme o exemplo onde
 remove o caractere de específico do índice que se encontra na
 string.//delete

 System.out.print("testStringBuffer
 (delete)= "+testStringBuffer);

testStringBuffer.deleteCharAt(5);//delete
 indice
 5

 System.out.println("(delete
 5)= "+testStringBuffer);



Saida:testStringBuffer
(delete)= surfing in Rio!(delete 5)= surfig in Rio!




insert(int
 offset, String s);Inserir
 uma String a partir do índice informado pelos
 parâmentros.//
 insert

System.out.print("testStringBuilder=
 "
 + testStringBuilder);

  
   
    
testStringBuilder.insert(7,
    "
    all day ");



System.out.println("(insert
  7)= "
  + testStringBuilder);

Saida:testStringBuilder=
  surfing in Rio!(insert 7)= surfing all day  in Rio!





reverse():Coloca
 todo o texto de forma reversa conforme podemos ver abaixo.//
 reverseSystem.out.print("testStringBuilder
 reverse"+testStringBuilder.reverse());Saida:testStringBuilder
 reverse= !oiR ni  yad lla gnifrus


toString():Algumas
 vezes utilizado para  imprimir a variável em forma de String ou
 para passar o parâmetro como String

//
 toString

System.out.print("testStringBuffer
 toString=”+testStringBuffer.toString())



GitHub=https://github.com/gmachado1/blog/tree/branche1/String-StringBuilder-StringBuffer