Conhecendo um pouco da classe String do Java
Como todo programador sabe String é um tipo de dado/estrutura/objeto que é utilizada para armazenar texto dentro de um programa sendo composta por uma série de caracteres, mas como estamos falando de Java vamos nos ater a String como um objeto, na verdade um objeto muito singular, pois ela se comporta um pouco diferente.
Começamos com a criação, como todo objeto ele pode ser criado utilizando a instrução new
.
String s = new String();
O código acima criará uma String vazia, então vamos criar um com algum conteúdo.
String s = new String("Algum texto");
Ok, mas a sintaxe acima ainda é diferente de como você deve estar acostumado a utilizar, como utilizamos objetos String o tempo todo existe um modo mais fácil de fazer isso!
String s = "Algum texto";
A pergunta que não quer calar “qual a diferença?”, a String criada com a instrução new
cria um novo objeto na memória como estamos acostumados e as criadas quando escrevemos um literal String(simplesmente colocando caracteres entre aspas dupla) utilizam um recurso para otimização de String muito utilizadas camada de Pool de Strings que reaproveita um objeto na memória.
String s1 = "João";
String s2 = "João";
String s3 = new String("João");
System.out.println("s1 == s2 : "+( s1 == s2 ) );//true
System.out.println("s1 == s3 : "+( s1 == s3 ) );//false
Quando comparamos s1
e s2
obtemos o resultado true
(verdadeiro) pois os dois objetos String estão no mesmo endereço de memória pois o objeto “João” foi criado no Pool de String e quando fazemos a atribuição s2 = "João"
objeto atribuído à s2
é o mesmo que está em s1
, já quando comparamos s1
e s3
obtemos o resultado false(falso) já que quando criamos o objeto s3
o fizemos com a instrução new
então não foi utilizado o Pool de String e sim criado um novo objeto em outra posição da memória, lembrando que quando utilizamos o operador de comparação "=="
com variáveis de referência a objetos estamos comparando na verdade os endereços de memória e não os valores contidos lá. Por isso não devemos utiliza o operador de comparação "=="
para comparar Strings e sim o método equals
fornecido pela classe String que compara valor dela.
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
System.out.println("s == \"texto\" : " + ( s == "texto") );//false
System.out.println("s.equals(\"texto\") : " + s.equals("texto") );//true
Quando comparamos com o operador "=="
ele irá comparar o endereço de “s” que foi criado dentro do método nextLine
com o endereço da String que está no Pool de String “texto”. Já na comparação feita com o método equals
ele irá comprar o caracteres contido em cada uma das Strings.
Imutabilidade
Algo que muitos programadores iniciantes não sabem é que os objetos String são imutáveis, ou seja, depois de serem criados eles não podem ser alterados. Quando concatenamos(juntamos) suas Strings na verdade estamos criando um novo objeto em um outro local da memória.
String s1 = "João";
s1 = s1 + " Antonio";
No código acima criamos um objeto no Pool(ou pegamos um já armazenado não sabemos) e colocamos sua referência em s1
, na linha 2 criamos um objeto no Pool “Antonio”, não armazenamos esta referência e sim utilizamos para concatenar com o objeto referenciado por s1
, criando um novo objeto String("João Antonio")
que será armazenado em algum outro lugar na memória e sua referência será armazenada em s1
, fazendo assim perdemos a referência a String “João”, mas o objeto não foi destruído ou modificado.
Métodos comuns da classe String
Os métodos a seguir são alguns utilizados da classe String.
charAt(int index): char
Retorna o caractere localizado no índice especificado, lembrando que o primeiro caractere tem índice 0.
String s1 = "Rodrigo";
System.out.println( s1.charAt(2) );//retorna o char 'd'
concat(String s): String
Anexa uma String passada por parâmetro ao final da String que chamou o método, os operadores "+"
e "+="
executam uma funções semelhantes.
String s2 = "Boteco";
System.out.println( s2.concat(" Digital") ); //retorna "Boteco Digital"
equals(): boolean
Compara a String que chamou o método com outra passada por parâmetro diferenciando maiúsculas de minusculas.
String s3 = "João";
System.out.println( s3.equals( "João" ) );//retorna true
System.out.println( s3.equals( "Pedro" ) );//retorna false
System.out.println( s3.equals( "joão" ) );//retorna false (j em minusculo)
equalsIgnoreCase(): boolean
Compara a String que chamou o método com outra passada por parâmetro “não” diferenciando maiúsculas de minusculas.
String s4 = "João";
System.out.println( s4.equalsIgnoreCase( "João" ) );//retorna true
System.out.println( s4.equalsIgnoreCase( "Pedro" ) );//retorna false
System.out.println( s4.equalsIgnoreCase( "joão" ) );//retorna true (j em minusculo)
length(): int
Retorna o número de caracteres da String que chamou o método.
String s5 = "Java";
System.out.println( s5.length() );// retorna 4
replace(char oldChar, char newChar): String
Substitui as ocorrências de um caractere(oldChar
) por um outro caractere(newChar
) na String que chamou o método.
String s6 = "rodrigo";
s6 = s6.replace("o", "*");//retorna r*drig*
System.out.println(s6);
subtring(int index): String , subtring(int index, int end): String
Retorna uma parte da String que chamou método, o primeiro parâmetro representa a posição a partir da qual a substring começa(iniciando em 0) e terminará no final. Se houver um segundo parâmetro a substring terminará nesta posição incluindo este caractere nela.
String s7 = "0123456789";
System.out.println(s7.substring(5)); // 56789
System.out.println(s7.substring(5,7)); // 56
toLowerCase(String s): String
Retorna uma String com todos os caracteres em minuscula.
String s8 = "AbCdEfGh";
System.out.println( s8.toLowerCase() );// retorna abcdefgh
toLowerCase(String s): String
Retorna uma String com todos os caracteres em maiúscula.
String s9 = "AbCdEfGh";
System.out.println( s8.toUpperCase() );// retorna ABCDEFGH
split(String regex)
Retorna um array de String sendo que cada um de seus elementos deste array é um pedaço da String que chamou o método dividida pelo caractere passo por parâmetro(também pode ser uma expressão regular)
String s10 = "teste1;teste2;teste3";
String[] array = s10.split(";");
System.out.println( array[0] ); // teste1
System.out.println( array[1] ); // teste2
System.out.println( array[2] ); // teste3
trim()
Retorna uma String que é a String utilizada para chamar o método mas sem os espaços em brando iniciais ou finais.
String s11 = " XXXX ";
System.out.println( "|"+s11.trim() +"|"); // retorna |XXXX|
StringBuilder
Levando o conceito de imutabilidade em consideração, quando temos que modificar uma String muitas vezes iremos criar muitos objetos String que irão ser abandonados no Pool de String como no exemplo abaixo.
String s = "";
for(int i = 0 ; i < 10 ; i++){
s = s + i;
}
Se você notar foram criadas na memória mais ou menos as seguintes String: “0” , “01” , “012”, “0123”, “01234”, 012345″, “0123456”, “01234567”, “012345678”, “0123456789”. Sendo que a maioria delas será abandonado no Pool desperdiçando memória.
Para corrigir este problema exite a classe StringBuilder
que permitir modificar uma String sem deixar objeto perdidos no Pool, segue um exemplo igual ao anterior utilizando a classe StringBuilder
.
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < 10 ; i++){
sb.append(i);
}
System.out.println( sb.toString() );
Alguns métodos de StringBuilder:
append(valor)
Este método adiciona o parâmetro(podendo ser int
, char
, double
, float
, long
, etc) ao final do objeto StringBuilder
que chamou o método.
delete(int star, int end)
Este método atualiza o objeto StringBuilder
retirando dele uma substring, sendo que o primeiro parâmetro é o inicio da substring e o segundo o final, sendo este caractere removido também.
StringBuilder sb2 = new StringBuilder("0123456789");
sb2.delete(3, 5); // atualiza para 01256789
insert(int offset, String s)
Este método insere um valor dentro do objeto StringBuilder
que chamou, sendo o primeiro parâmetro a posição em que o valor vai ser inserido e o segundo próprio valor(podendo ser int
, char
, double
, float
, long
, etc) a ser inserido.
StringBuilder sb3 = new StringBuilder("0123456789");
sb3.insert(5, "XXX"); // atualiza para 01234XXX56789
reverse()
Este método inverte os caracteres dentro do objeto StringBuilder
, deixando o primeiro caractere como último e o último como primeiro.
StringBuilder sb4 = new StringBuilder("Rodrigo");
sb4.reverse(); // atualiza para "ogirdoR"
toString()
Este método retorna o valor do objeto StringBuilder
ou seja a String que estávamos construindo.
Lembrando que os métodos append()
, delete()
, insert()
, reverse()
retornam o próprio objeto que o chamou permitindo encadear suas chamadas.
StringBuilder sb5 = new StringBuilder();
sb5.append("Rodrigo").append("Aramburu").reverse();// atualiza para "urubmarAogirdoR"
Bom era isso a classe String tem vários métodos que valem a pena ver consulte a documentação para mais detalhes.