Como comparar uma string recebida de java em c

Muitos iniciantes em Java frequentemente se esquecem que uma string em particular não é um tipo primitivo de dado, tal como int ou char, mas sim um objeto, ou seja, não se pode utilizar o operador == para comparar objetos. A classe Object, que é a classe raiz da hierarquia de classes em Java, oferece o método equals(Object obj) que retorna um valor booleano true, se o objeto que invoca tal função for igual ao outro passado como parâmetro dessa função, ou false caso contrário. O operador == entre objetos apenas checa se suas referências são iguais, mas não seus conteúdos.

String s1 = new String("banana"); String s2 = new String("banana"); //Bloco 1 System.out.println(s1.equals(s2));  //true //Bloco 2 System.out.println(s1 == s2);   //false

O resultado da comparação do "Bloco 1" acima, utilizando a função equals, é true. E do "Bloco 2" é false, apesar de s1 e s2 serem objetos do tipo String, com o mesmo conteúdo, eles possuem endereços diferentes na memória. Mas se modificarmos a criação das strings, sem utilizar o operador new, o resultado será true em ambos os casos.

String s3 = "abacaxi"; String s4 = "abacaxi"; //Bloco 1 System.out.println(s3.equals(s4));  //true //Bloco 2 System.out.println(s3 == s4);   //true

Quando criamos strings literais, usando apenas aspas duplas, o conteúdo delas vão para um pool de strings, conforme figura abaixo.

Então s3 e s4 estão se referindo ao mesmo objeto dentro do pool de strings, por isso s3 == s4 retorna true. E quando o objeto string é criado utilizando operador new, um espaço na memória heap do Java é alocado exclusivamente para aquele objeto, portanto s1 == s2 retorna false nesta situação. O mecanismo de pool de strings auxilia na economia de espaço em memória para o ambiente Java Runtime, embora normalmente leve mais tempo para criar a string. O aconselhável é utilizar o método equals quando quisermos comparar os valores de duas strings para saber se são iguais ou não.

O artigo retrata sobre a manipulaç�o de texto em Java utilizando as classes String, StringBuffer e StringBuilder, e como melhorar a utilizaç�o de mem�ria, o desempenho do c�digo e facilitar a sua manutenç�o trabalhando com objetos dessas tr�s classes.

Guia do artigo:

Os m�todos dispon�veis na classe String podem servir para uma simples junç�o de texto, comparaç�o de conte�do, busca de determinados dados em mensagens advindas de sistemas externos, dentre muitas outras funcionalidades. As classes StringBuffer e StringBuilder, por sua vez, podem ser utilizadas para reduzir a criaç�o de objetos desnecess�rios na mem�ria, possibilitando que uma mesma String seja modificada diversas vezes.

Saber como funciona a criaç�o de objetos String no pool e na mem�ria, bem como a utilizaç�o e o resultado da execuç�o dos m�todos desta classe melhora o desempenho do c�digo. Esta melhoria tamb�m � conseguida atrav�s da utilizaç�o das classes StringBuffer e StringBuilder, pois elas trabalham com objetos String mut�veis que ocupam menos espaço em mem�ria.

Neste artigo ser�o demonstradas algumas maneiras de como trabalhar com �texto� na linguagem de programaç�o Java. Das opç�es dispon�veis, String, StringBuffer e StringBuilder s�o certamente as classes mais utilizadas. Cada uma delas apresenta particularidades com relaç�o � criaç�o de objetos na mem�ria e no relacionamento com as vari�veis de refer�ncia, assim como apresentam tamb�m m�todos espec�ficos para a manipulaç�o de seus conte�dos.

Por isso, abordaremos como fazer uso destas classes de maneira eficiente e as melhores situaç�es onde utilizar cada uma delas. Um passo inicial para que o leitor possa trabalhar de modo a atender aos requisitos do sistema/c�digo em que estiver trabalho e adquirir o conhecimento necess�rio para se aprofundar mais no tema futuramente.

O que s�o Strings?

Em Java, String � uma sequ�ncia de caracteres utilizada para representaç�o e manipulaç�o de texto. Quando � necess�rio representar informaç�es textuais em uma aplicaç�o, seja ela para Desktop ou Web, como nome de pessoas, informaç�es sobre endereço ou coment�rios em uma mat�ria no jornal, inst�ncias da classe String ser�o criadas invariavelmente. Isto �, sempre que precisarmos mostrar alguma informaç�o em um sistema, dificilmente vamos conseguir isso sem o aux�lio de Strings.

Em uma vis�o mais t�cnica, String � uma classe presente no Java desde a vers�o 1.0 do JDK que implementa a interface CharSequence (al�m de Serializable e Comparable, mas essas duas n�o s�o interessantes para este artigo). Assim, podemos dizer que Strings nada mais s�o do que uma cadeia ordenada de caracteres.

Como utilizar Strings em Java

A classe String permite a criaç�o de suas inst�ncias de diversas maneiras. Ela possui v�rios construtores que recebem diversos tipos de par�metros. Pelo fato de ser uma classe amplamente utilizada, ela tamb�m fornece um �atalho� para a criaç�o de forma mais r�pida de seus objetos, como pode ser observado no c�digo da Listagem 1.

Listagem 1. Maneiras de declarar e inicializar Strings.

package principal; public class ClassePrincipal { public static void main(String[] args) { String minhaString1 = new String(); minhaString1 = "Java"; String minhaString2 = "Java"; String minhaString3 = new String("Java"); String minhaString4 = ""; char[] meusChars = new char[] {'J','a','v','a'}; String minhaString5 = new String(meusChars); } }

Vamos � explicaç�o dos pontos pertinentes:

  • Linha 6: A classe

    String

    , assim como qualquer classe em Java, pode ser instanciada com a utilizaç�o da palavra chave new. Neste caso, est� sendo criado um objeto

    String

    vazio que � atribu�do � vari�vel de refer�ncia

    minhaString1

    ;
  • Linha 7: A vari�vel

    minhaString1

    recebe o valor �Java�. Como a vari�vel j� foi declarada na linha anterior, neste momento acontece apenas a atribuiç�o do conte�do � vari�vel;
  • Linha 8: Representa a maneira mais r�pida e f�cil de criar um novo objeto desta classe e atribu�-lo a uma vari�vel (no caso,

    minhaString2

    );
  • Linha 9: H� diversos construtores na classe

    String

    . Esta linha demonstra a utilizaç�o de um deles: passar um objeto

    String

    no construtor de modo a criar um novo objeto

    String

    . Com relaç�o � criaç�o de objetos na mem�ria, h� uma diferença consider�vel no modo como as linhas 8 e 9 o fazem. Essa diferença ser� explicada mais adiante, na seç�o �Como s�o criados objetos da classe

    String

    �;
  • Linha 10: Aqui uma

    String

    vazia � criada utilizando-se o mesmo mecanismo de �atalho� que foi demonstrado na linha 8, s� que o conte�do para o qual aponta a vari�vel minhaString4 � uma

    String

    vazia. Pode-se dizer que, com relaç�o ao conte�do, as linhas 6 e 10 fazem a mesma coisa: criam uma

    String

    vazia;
  • Linhas 12 e 13: Como j� foi comentado neste artigo, a classe

    String

    possui diversos construtores. N�o cabe aqui tentarmos demonstrar a utilizaç�o de cada um deles. Estas duas linhas demonstram mais um exemplo de como podemos criar objetos

    String

    a partir de outros objetos passados como par�metro no construtor. A vari�vel

    minhaString5

    tem o mesmo conte�do das vari�veis

    minhaString1

    ,

    minhaString2

    e

    minhaString3

    , por�m foi inicializada de uma maneira diferente das demais, recebendo um array de char.

Estes s�o alguns modos de se declarar e atribuir valor �s vari�veis do tipo String. Agora veremos alguns dos m�todos utilizados para se manipular o conte�do destas vari�veis.

M�todos �teis da classe String

Para se trabalhar com texto, a classe String oferece diversos m�todos utilit�rios. Por quest�es de espaço, n�o ser�o descritos todos aqui. Vamos apenas comentar aqueles que s�o mais utilizados no dia-a-dia do programador. Logicamente, dependendo do sistema que esteja sendo desenvolvido, alguns m�todos ser�o mais utilizados que outros, mas independente do que seja necess�rio, a classe String oferece o suporte necess�rio para operaç�es envolvendo texto: quebr�-lo em v�rias partes, fazer busca de determinado conte�do, converter a String em bytes, verificar se o texto começa ou termina com um dado conjunto de caracteres, comparar se uma String � igual � outra (o m�todo equals() � definido na classe Object), dentre outros.

public String replace(CharSequence target, CharSequence replacement)

O m�todo replace() faz a substituiç�o de um determinado conjunto de caracteres por outro, retornando uma nova String. Um exemplo de sua utilizaç�o pode ser visto em f�runs de discuss�o, onde os administradores criam uma lista de palavras de baixo cal�o que n�o podem ser publicadas. Caso algu�m escreva tais palavras, elas ser�o automaticamente substitu�das por outras, ap�s uma busca adequada (que pode ser feita utilizando o m�todo contains(), explicado mais adiante). Vejamos o c�digo abaixo:

String s = "Este coment�rio foi p�ssimo!"; s = s.replace("p�ssimo","ruim"); System.out.println(s);

A sa�da na linha 3 ser� �Este coment�rio foi ruim!�. O m�todo replace() � Case Sensitive, ou seja, faz diferenciaç�o entre mai�sculas e min�sculas. Portanto, se na linha 2 estivesse escrito s = s.replace(�P�ssimo�,�ruim�) nada seria alterado e a frase inicial seria impressa na sa�da padr�o. Tamb�m � v�lido lembrar que o m�todo replace() busca todas as ocorr�ncias do primeiro par�metro e realiza a substituiç�o pelo segundo. Perceba o que acontece com a busca na pr�xima sentença:

String s = "Gosto de comer frango com batata. N�o gosto de batata frita."; s = s.replace("batata","polenta"); System.out.println(s);

Aqui a impress�o ser� �Gosto de comer frango com polenta. N�o gosto de polenta frita.�.

Por fim, o m�todo replace() � sobrecarregado e pode receber apenas um caractere (do tipo primitivo char) como par�metro para que seja feita a substituiç�o. Exemplo:

String s = "arara"; s = s.replace(�a�,�e�); // recebendo um char como par�metro System.out.println(s);

A sa�da na linha 3 ser� �erere�.

O m�todo trim() retorna uma String sem os espaços em branco no começo e no final da mesma. � �til quando se trabalha com preenchimento de formul�rios. Antes de salvar no banco de dados as informaç�es preenchidas pelo usu�rio na tela, pode-se chamar o m�todo trim() em todos os campos texto preenchidos pelo operador, de modo a evitar que espaços em branco desnecess�rios sejam gravados, economizando espaço no banco de dados. O c�digo abaixo exemplifica a utilizaç�o do m�todo trim():

String s = " Java Magazine "; s = s.trim();

Ap�s a execuç�o do comando na linha 2, a vari�vel de refer�ncia s apontar� para a nova String criada sem os espaços que existiam na linha 1 (�Java Magazine�). Todavia, como pode ser observado, o espaço em branco do meio da palavra n�o foi removido.

public boolean contains(CharSequence s)

O m�todo contains() n�o tem como retorno uma nova String, mas sim um boolean. Ele avalia se a String original cont�m a String passada como par�metro para o m�todo. Este m�todo pode ser utilizado para verificar, por exemplo, se determinado nome est� na lista de aprovados de um concurso p�blico ou vestibular. Ou ainda, se um dado espec�fico foi recebido em uma mensagem enviada por outro sistema para realizar validaç�o. As linhas abaixo demonstram uma utilizaç�o do m�todo contains():

String s = "001MARCOS PAULO M19803112"; System.out.println(s.contains("MARCOS"));

Um detalhe interessante � que o m�todo contains() tamb�m � Case Sensitive. No caso do c�digo acima, o resultado ser� true, por�m, se a String passada como par�metro estivesse escrita �Marcos�, o resultado seria false.

O m�todo lengh() retorna um int indicando o tamanho da String, ou seja, a quantidade de caracteres que h� na String atual. � comum ser utilizado em loops for e blocos de condiç�o if. O trecho a seguir demonstra a aplicaç�o deste m�todo:

System.out.println(" Java ".length());

A linha 1 imprimir� �6�, que � a quantidade de caracteres contida na String � Java � (aqui o m�todo foi invocado diretamente na inst�ncia da classe, sem a utilizaç�o de uma vari�vel de refer�ncia). Perceba que os espaços em branco tamb�m s�o considerados como caracteres. Se fiz�ssemos uma chamada ao m�todo trim() encadeado com length(), da forma � Java �.trim().length(), a linha 1 exibiria o valor �4� na sa�da padr�o.

public String toUpperCase()

O m�todo toUpperCase() retorna uma nova String com o mesmo conte�do da original, s� que com todos os caracteres em letras mai�sculas. Assim como o m�todo trim(), toUpperCase() tamb�m pode ser utilizado antes de salvar dados de um formul�rio na base de dados. Como as pessoas n�o possuem o mesmo padr�o de digitaç�o (algumas digitam todo o texto em min�sculo, Outras Começam Todas As Palavras De Uma Frase Com Letras Mai�sculas, E H� TAMB�M AQUELAS QUE ESQUECEM O CAPS LOCK LIGADO), o m�todo toUpperCase() pode ser a soluç�o para este problema, salvando todos os dados do cliente em letra mai�scula. Veja um exemplo abaixo:

String s1 = "rodolfo rodrigues"; String s2 = "Alfredo Augusto"; String s3 = "JONNY DEBRUCE"; System.out.println(s1.toUpperCase()); System.out.println(s2.toUpperCase());

A sa�da ser�, respectivamente:

RODOLFO RODRIGUES

ALFREDO AUGUSTO

JONNY DEBRUCE

Existe ainda o m�todo toLowerCase(), o �irm�o menor� do m�todo toUpperCase(), por�m menos utilizado. Ele tamb�m retorna uma nova String com o mesmo conte�do da original, mas com todos os caracteres em letras min�sculas. Se na linha 6 estivesse escrito System.out.println(s3.toLowerCase()) a sa�da seria �jonny debruce�.

public String substring(int beginIndex)

O m�todo substring() retorna uma parte do texto original a partir do �ndice especificado. Ele recebe como par�metro um int que indica o ponto de partida (iniciado em zero) pelo qual se deve iniciar a pesquisa. A partir deste �ndice o m�todo copia tudo que estiver at� o final da palavra. H� outra implementaç�o deste m�todo que recebe um �ndice para indicar o t�rmino da pesquisa, mas ele n�o ser� abordado aqui. O m�todo substring() pode ser �til para fazer buscas em Strings e capturar determinadas informaç�es, por exemplo:

String s = "Universidade"; System.out.println(s.substring(7));

Como o �ndice da String inicia em zero, a sa�da do comando ser� �idade�. Note que o caractere que estiver ocupando a posiç�o do �ndice inicial de pesquisa tamb�m ser� inclu�do na String de resultado. A Tabela 1 demonstra o funcionamento do m�todo para a palavra �Universidade�.

Palavra

U

N

I

V

E

R

S

I

D

A

D

E

�ndice

0

1

2

3

4

5

6

7

8

9

10

11

Tabela 1. Caracteres da String �Universidade� copiados pelo m�todo substring().

Os m�todos apresentados aqui s�o apenas alguns dos muitos presentes na classe String. Por�m, sabendo-se trabalhar com os que j� foram citados � poss�vel realizar muitas tarefas do cotidiano da programaç�o em Java.

A Tabela 2 apresenta uma descriç�o sucinta de outros m�todos �teis presentes na classe String.

M�todo

Descriç�o

public char charAt(int index)

Retorna o caractere que estiver na posiç�o do �ndice passado como par�metro (iniciado em zero).

public String concat(String str)

Retorna a junç�o da String na qual o m�todo est� sendo chamado adicionando ao seu final a String passada por par�metro (�str�).

public int indexOf(int ch)

Tem funç�o inversa ao charAt(): retorna a posiç�o (�ndice) em que se encontra na String o caractere pesquisado.

public boolean startsWith(String prefix)

Retorna true se a String iniciar com o valor passado como par�metro (Case Sensitive). Caso contr�rio, retorna false.

public boolean endsWith(String suffix)

Mesmo funcionamento do startsWith(), s� que verificando o final da String na qual o m�todo foi invocado.

public boolean equalsIgnoreCase(String anotherString)

Compara se duas Strings s�o iguais. Para que isso ocorra, � necess�rio que elas tenham o mesmo comprimento e os caracteres correspondentes nas duas sequ�ncias sejam os mesmos, independente se mai�sculos ou min�sculos.

Tabela 2. Outros m�todos �teis presentes na classe String.

At� o momento vimos o que fazer para criar Strings e tamb�m como manipular seu conte�do, agora vamos analisar uma das particularidades das Strings: a imutabilidade.

Como s�o criados objetos da classe String

Certamente voc� j� ouviu uma frase parecida com esta: �Strings s�o imut�veis, seu valor nunca poder� ser alterado�. Certo... v�rios artigos e livros falam da imutabilidade das Strings, mas o que isso significa na pr�tica? O que isso influencia no meu c�digo e como eu posso tirar proveito disso? Vamos tentar responder a estas quest�es. Por exemplo, quando voc� escreve uma linha de c�digo parecida com esta:

O que acontece na pr�tica �:

1. Uma nova String com o valor �Java� � criada no pool de Strings (em breve falaremos sobre pool de Strings);

2. A vari�vel de refer�ncia s aponta para o valor criado.

Uma vez criada no pool, a String �Java� n�o poder� ser alterada. Mas qual � a vantagem disso? Simples: ela ser� reutilizada em outras partes do c�digo que façam refer�ncia � mesma String (outras vari�veis de refer�ncia apontar�o para a mesma String no pool). � a� que entra o chamado �pool de Strings�. O pool � uma esp�cie de �lista� que armazena todas as Strings criadas no programa. Dessa forma, toda vez que atribuirmos uma String a uma vari�vel de refer�ncia, antes da JVM (Java Virtual Machine) criar uma nova String na mem�ria, ela verifica se este valor j� est� contido no pool. Caso positivo, n�o � necess�rio criar uma nova, fazendo com que a vari�vel de refer�ncia apenas �aponte� para a String existente. Ent�o, na verdade, temos um passo anterior aos dois descritos previamente:

1. A JVM verifica se a String �Java� j� existe no pool;

a. Se j� existe, a vari�vel de refer�ncia s apontar� para este valor;

b. Sen�o, uma nova String com o valor �Java� ser� criada no pool de Strings e a vari�vel de refer�ncia s apontar� para este valor.

Vejamos outro exemplo:

String s1 = "Brasil"; String s2 = "Brasil"; s1 = "Argentina";

Eis o que aconteceu no c�digo durante a sua execuç�o (vamos assumir que este c�digo est� inserido em um m�todo main() que cont�m somente estas tr�s instruç�es):

  • Na linha 1, a JVM verificou que a String �Brasil� (Case Sensitive) ainda n�o havia sido criada no pool de Strings, ent�o, criou uma nova

    String

    no pool e a vari�vel de refer�ncia s1 apontou para a

    String

    rec�m-criada;
  • Na linha 2, antes de fazer a atribuiç�o de valor para s2, a JVM foi novamente ao pool e verificou que j� existe uma

    String

    chamada �Brasil�. Por isso, n�o foi criada uma nova

    String

    no pool;
  • A vari�vel s2 passa a fazer refer�ncia � mesma

    String

    criada anteriormente;
  • Na linha 3 a JVM faz o mesmo procedimento da linha 1. Como n�o existe a

    String

    �Argentina�, ela cria uma nova

    String

    no pool;
  • Por fim, a vari�vel s1 aponta para a �Argentina� criada no pool e deixa de apontar para a

    String

    �Brasil�.

A Figura 1 demonstra visualmente como todo esse procedimento acontece por tr�s dos panos.

Como comparar uma string recebida de java em c
Como comparar uma string recebida de java em c
Figura 1. Como acontece a criaç�o de Strings no pool.

Ok, mas o que tudo isso tem a ver com a imutabilidade das Strings?

Imagine que em outros pontos do seu c�digo voc� precise alterar a String �Brasil�. Como essa String � compartilhada por outras vari�veis de refer�ncia (s1 e s2), se n�o houvesse a imutabilidade, cada alteraç�o feita em uma das vari�veis que apontam para este conte�do seria refletida nos demais pontos onde s�o feitas refer�ncias ao mesmo texto, o que poderia nos trazer problemas. Por isso que grande parte dos m�todos da classe String n�o tem retorno void, mas sim String. Dessa forma, eles retornam sempre uma nova String modificada. A original estar� l�, intacta no pool, enquanto novas Strings estar�o sendo criadas. Vejamos um exemplo para ilustrar o conceito:

String s1 = "Meu nome era "; String s2 = "Michel"; String s3 = s1; s1.replace("era","�"); String s4 = s3.replace("era","sempre foi "); s3 = s4 + s2; System.out.println(s3);

Analisando cada uma das linhas:

  • Linha 1: Criada no pool de Strings, a String �Meu nome era � � associada � vari�vel de refer�ncia s1;
  • Linha 2: Criada no pool de Strings, a String �Michel� � associada � vari�vel de refer�ncia s2;
  • Linha 3: A vari�vel de refer�ncia s3 passa a fazer refer�ncia � String definida na linha 1. Deste modo nenhuma nova

    String

    � criada no pool;
  • Linha 4: Neste ponto temos uma das grandes �pegadinhas� dos exames de certificaç�o. O resultado da execuç�o desta linha � a criaç�o de uma nova

    String

    , com o conte�do �Meu nome � �. Por�m, o retorno do m�todo n�o � atribu�do a nenhuma vari�vel de refer�ncia, deixando a nova

    String

    �perdida� no pool, pois n�o h� ningu�m que faça refer�ncia a ela. Dessa forma, a

    String

    referenciada por s1 n�o � alterada. As Strings �era� e �� tamb�m s�o adicionadas ao pool de Strings nesta linha;
  • Linha 5: Novamente uma String � criada no pool, como resultado da execuç�o do m�todo

    replace()

    : �Meu nome sempre foi �. Esta nova String � associada � vari�vel de refer�ncia s4. Vale a pena ressaltar que as vari�veis s1 e s3 ainda fazem refer�ncia �

    String

    �Meu nome era �. Se a

    String

    referenciada por s1 tivesse sido alterada na linha 9, o resultado da linha 10 n�o seria o esperado, pois como s3 tamb�m referencia a mesma

    String

    , o m�todo

    replace()

    n�o teria feito nenhuma alteraç�o. H� tamb�m a criaç�o da

    String

    �sempre foi� no pool;
  • Linha 6: Vemos aqui um exemplo de como o Java oferece a sobrecarga do operador �+� para manipulaç�o de Strings. A vari�vel s3 recebe a concatenaç�o (junç�o) das Strings referenciadas por s4 e s2. Esta � uma das maneiras mais utilizadas para unir duas ou mais Strings. O m�todo

    concat()

    tamb�m faz concatenaç�o de Strings, por�m � menos utilizado pelo fato do operador �+� ser uma maneira mais r�pida de faz�-lo;
  • Linha 7: � impresso na sa�da padr�o �Meu nome sempre foi Michel�.

Agora vamos entender quantas Strings foram criadas no pool de Strings:

  • Linha 1: Uma String �Meu nome era �;
  • Linha 2: Uma String �Michel�;
  • Linha 3: Nenhuma String � criada no pool, pois a

    String

    na linha 1 � reutilizada;
  • Linha 4: Atenç�o! Aqui s�o criadas tr�s novas Strings: �era�, �� e �Meu nome � �. Por�m, nenhuma delas � referenciada por qualquer vari�vel;
  • Linha 5: Duas Strings novas s�o criadas: �sempre foi � e �Meu nome sempre foi �. Esta �ltima � atribu�da � vari�vel s4. A String �era� j� existe no pool e n�o ser� criada novamente;
  • Linha 6: Mais uma

    String

    � criada no pool, �Meu nome sempre foi Michel�.

Como pudemos observar, um total de oito Strings foram criadas no pool, entretanto algumas delas n�o s�o referenciadas por nenhuma vari�vel e s�o eleg�veis para serem coletadas pelo Garbage Collector (o funcionamento do Garbage Collector � assunto para outro artigo).

Para aperfeiçoar a utilizaç�o das Strings, uma boa pr�tica � valer-se de um artif�cio bastante comum que � a criaç�o de constantes (vari�veis declaradas como public static final). Com as constantes, as Strings j� s�o criadas no pool e podem ser reutilizadas em v�rias partes do c�digo, diminuindo assim a criaç�o de objetos desnecess�rios. Elas dificilmente ser�o eleg�veis para serem coletadas pelo Garbage Collector, pois sempre haver� uma vari�vel referenciando-a. Segue um exemplo de declaraç�o de uma constante:

public static final String nomeDaEmpresa = "Info Telecom LTDA.";

Foi comentado na seç�o �Como utilizar Strings em Java� que a classe String apresenta uma particularidade interessante na criaç�o de inst�ncias da sua classe. Durante a explicaç�o dos m�todos desta classe, os exemplos demonstram a criaç�o de Strings sem a utilizaç�o do construtor e da palavra chave new. Este � um detalhe na criaç�o de objetos que pode fazer grande diferença com relaç�o ao consumo de mem�ria da aplicaç�o. Analisemos o c�digo abaixo:

String s = new String("Java");

Nesta linha, acontece a criaç�o de uma String �Java� no pool de Strings e tamb�m um novo objeto String na mem�ria comum, que ser� referenciado por s. Ou seja, sempre que � criada uma String atrav�s da palavra chave new, um novo objeto ser� criado na mem�ria. A n�o ser que seja fundamental para o seu c�digo, procure evitar a criaç�o de Strings desta forma.

Durante a codificaç�o, por�m, pode ser necess�ria uma constante alteraç�o de objetos String (para a criaç�o de sentenças SQL, por exemplo). Com isso, se optar por manipular as sentenças utilizando objetos String, voc� poder� ter v�rios deles abandonados ao final da execuç�o da consulta no pool. Para resolver este problema, h� outras duas classes que podem ser usadas para se trabalhar com Strings sem que sejam criados v�rios objetos String desnecess�rios e ocupar menos mem�ria: StringBuffer e StringBuilder.

StringBuffer e StringBuilder

Conforme j� descrevemos, Strings s�o imut�veis: elas n�o t�m seus valores alterados ap�s sua criaç�o. Entretanto, em alguns momentos necessitamos fazer v�rias modificaç�es em uma mesma String. Para estes casos, as classes StringBuffer e StringBuilder auxiliam na manipulaç�o de Strings sem a criaç�o de v�rios objetos na mem�ria e, agora sim, alterando o mesmo objeto diversas vezes. Ambas as classes t�m o mesmo prop�sito: trabalhar com objetos de texto que podem ser alterados. No entanto, h� uma diferença importante entre elas (al�m da classe StringBuilder estar dispon�vel apenas a partir da vers�o 1.5 do JDK), a sincronizaç�o.

A classe StringBuffer � considerada uma �classe sincronizada�, ou seja, possui seus m�todos sincronizados (somente uma Thread pode acessar por vez). Sabemos que n�o � poss�vel declarar uma classe com o modificador de acesso syncronized, mas pode-se faz�-lo nos m�todos, e � isso que a classe StringBuffer faz.

A explicaç�o t�cnica sobre sincronizaç�o seria assunto para um artigo sobre �Threads�, mas basicamente podemos dizer que m�todos sincronizados s�o mais �lentos� do que m�todos n�o sincronizados, visto que somente uma Thread pode executar cada m�todo por vez. Assim, a classe StringBuilder seria mais indicada por ter um melhor desempenho do que sua predecessora, para aplicaç�es nas quais a velocidade da execuç�o � importante. A classe StringBuffer, por sua vez, � indicada para aplicaç�es que envolvem utilizaç�o de v�rias linhas de execuç�o simult�neas (threads), como sistemas Web.

Analisemos o trecho de c�digo que utiliza a classe StringBuilder:

String tabela = "funcionario"; String orderBy = " ORDER BY nome"; StringBuilder sql = new StringBuilder("SELECT cpf, nome "); sql.append("FROM "); sql.append(tabela); sql.append(" WHERE sexo = 'M'").append(orderBy);

Vejamos o que acontece a partir da linha 3. � criado um objeto StringBuilder e atribu�do � vari�vel de refer�ncia sql. Nas linhas seguintes, s�o feitas v�rias chamadas ao m�todo append(), de modo que novos dados s�o adicionados ao objeto criado. Perceba que, ao contr�rio dos objetos String, o StringBuilder n�o necessita que o resultado da execuç�o do m�todo append() seja atribu�do novamente � vari�vel sql que est� referenciando o objeto (por exemplo, na linha 4 n�o � feito: sql = sql.append(�FROM�)). O retorno do m�todo append() � o mesmo objeto que foi criado na linha 3, modificado de acordo com os par�metros passados. Dessa forma, apenas um objeto StringBuilder foi criado e alterado durante a execuç�o do c�digo.

Um detalhe a ser notado � que, assim como a classe String, os m�todos das duas outras classes t�m como retorno um objeto StringBuilder / StringBuffer. Assim, eles podem ser encadeados em v�rias chamadas sequenciais. Apesar de dificultar um pouco a manutenç�o do c�digo, � um artif�cio v�lido. Verifiquemos as seguintes instruç�es:

StringBuffer buffer = new StringBuffer("2468"); buffer.reverse().insert(1,"xxx").append("999"); System.out.println(buffer.toString());

A sa�da deste c�digo � �8xxx642999�. Para entender o que aconteceu, vejamos linha por linha:

  • Linha 1: � criado um novo objeto

    StringBuffer

    com o valor �2468� e atribu�do � vari�vel buffer;
  • Linha 2: Aqui acontece a execuç�o de tr�s m�todos, sendo que o resultado da chamada do m�todo mais � esquerda ser� o objeto que ir� chamar o m�todo seguinte. No caso, o primeiro m�todo a ser executado ser� o

    reverse()

    . Como resultado desse m�todo, temos o mesmo objeto

    StringBuffer

    invertido, com o valor �8642�. Este objeto, por sua vez, faz uma chamada ao m�todo

    insert()

    , que ir� inserir no �ndice 1 (lembrando que os �ndices iniciam em zero) o valor �xxx�, retornando assim o objeto

    StringBuffer

    �8xxx642�. Por fim, o m�todo

    append()

    adiciona o conte�do �999� ao final do objeto;
  • Linha 3: Acontece a impress�o na sa�da padr�o do sistema do valor �8xxx642999�.

O trecho de c�digo demonstrado acima � equivalente a:

StringBuffer buffer = new StringBuffer("2468"); buffer.reverse(); buffer.insert(1,"xxx"); buffer.append("999"); System.out.println(buffer.toString());

A Figura 2 mostra visualmente como acontece a modificaç�o do objeto StringBuffer na mem�ria. Perceba que a vari�vel buffer aponta sempre para o mesmo objeto.

Como comparar uma string recebida de java em c
Como comparar uma string recebida de java em c
Figura 2. Modificaç�es ocorridas em um �nico objeto

StringBuffer

na mem�ria.

Al�m dos outros m�todos que possibilitam a manipulaç�o de texto (insert(), delete(), reverse(), substring(), trimToSize(), replace() e demais), �Builders� e �Buffers� s�o comumente usadas para concatenar mensagens (de erro, warning ou sucesso) a serem exibidas ao operador e tamb�m na criaç�o de mensagens que devem ser enviadas a outros sistemas (geralmente sistemas legados, escritos em outras linguagens, como Cobol e RPG/AS400) via fila MQ series ou RTP (Real Time Protocol), para transfer�ncia de dados. Estas mensagens geralmente possuem um layout pr�-definido, contendo as informaç�es esperadas e os respectivos tamanhos dos campos a serem enviados.

Na obra de Katy Sierra e Bert Bates (vide seç�o Livros) � descrita outra utilizaç�o das classes StringBuffer e StringBuilder: �Um emprego comum dos objetos StringBuffer � na E/S (entrada e sa�da) de arquivos quando fluxos grandes de entrada e com alteraç�o constante est�o sendo manipulados pelo programa. Nesses casos, grandes blocos de caracteres s�o manipulados como unidade, e os objetos StringBuffer � (sic) a maneira ideal de manipular um bloco de dados, pass�-lo adiante e, em seguida, reutilizar o mesmo espaço na mem�ria para manipular o bloco seguinte.�

Conclus�es

Este artigo demonstrou a diferença entre criar um objeto String utilizando ou n�o o operador new e o que isso representa com relaç�o aos objetos na mem�ria. Tamb�m vimos alguns dos m�todos mais usados da classe String, que podem ser usados desde uma simples verificaç�o de senha em uma tela de login at� tratamentos complexos em mensagens recebidas por sistemas externos. A imutabilidade das Strings tamb�m foi abordada, demonstrando como podemos evitar a criaç�o de objetos desnecess�rios e o desperd�cio de mem�ria com a utilizaç�o de constantes.

Por fim, comentamos sobre as classes String mut�veis: StringBuffer e StringBuilder. Elas auxiliam o trabalho com texto fornecendo objetos que podem ser modificados poupando espaço na mem�ria. Quando necessitamos trabalhar com blocos de texto que precisam ser modificados frequentemente, estas duas classes s�o as mais indicadas.

Certamente n�o abordamos tudo o que envolve a manipulaç�o de texto. Todas as tr�s classes disp�em de in�meros m�todos para manipular texto, e o JavaDoc da Sun fornece um grande aux�lio para investigaç�es sobre seus funcionamentos.

JavaDoc da Sun para a vers�o 1.4 da linguagem.
java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html

Guia completo de estudos para certificaç�o em Java, Philip Heller e Simon Roberts, Ed. Ci�ncia Moderna, 2004

Livro voltado para os estudos das cerificaç�es SCJP e SCJD. Possui linguagem simples e acompanha um CD.

Certificaç�o Sun para programador & desenvolvedor Java 2 (3� Ediç�o), Kathy Sierra e Bert Bates, Ed. Alta Books, 2003

O livro mais indicado para estudos de certificaç�o para a vers�o 1.4 do Java. Tamb�m aborda SCJP e SCJD. Cont�m v�rios exerc�cios desafiadores e um conte�do bem explicado. O livro � bastante divertido de ler e n�o h� problemas com traduç�o.

Confira tamb�m