Alguns programadores, inclusive eu, acham besteira estudar instância de
objetos no java. A prova SCJP trabalha com assuntos deste paradigma,
porém retrata situações que ficamos confusos. Por esse motivo resolvi
fazer um rápido tutorial estilo "pegadinha" onde eu mostra um questão
típica do teste e você se descobre com dúvidas referentes a um conteúdo
tão macificado (ou achamos que está macificado).
Veja o programa abaixo:
public class Test9 {
static String s1 = "Guilherme";
String s2 = "Guilherme";
public static void main(String args[]) {
Test9 a = new Test9();
String s3 = "Guilherme";
String s4 = new String(s1);
String s5 = s1;
String s6 = a.s2;
// Aqui aparecem as dúvidas
System.out.println( s1 == a.s2 );
System.out.println( s1 == s3 );
System.out.println( s1 == s4 );
System.out.println( s1 == s5 );
System.out.println( a.s2 == s3 );
System.out.println( a.s2 == s4 );
System.out.println( a.s2 == s5 );
System.out.println( a.s2 == s6 );
System.out.println( s4 == s5 );
System.out.println( s1.equals(a.s2) );
System.out.println( s1.equals(s6) );
}
}
Qual será a saída do programa (true, false...)?
Antes de continuar o artigo, tente responder (mentalmente, se possível, pois na prova seria assim).
Agora que você já respondeu, vamos às explicações:
Primeiro detalhe: Você precisa entender (e acho que entende) que
ao comparar Strings com ==, você está comparando os objetos
instânciados, ou seja, a variável de instância s1 referencia o mesmo
objeto que a variável de instância s2. Assim que se lê a comparação com
==.
Segundo detalhe: Ao se comparar Strings com o método equals(), o
valor da String que é comparado (veja a API java). Isso você já sabe,
tenho certeza! Atente-se que a comparação é sensitive case.
Terceiro detalhe: As variáveis estáticas são instâncias normais
também, exceto pelo fato de que não estão associadas a determinada
instância da classe a qual pertence. Ela pertence à classe. Por exemplo,
a instância a de Test9 permitiu o acesso à variável de instância
interna s2, mas a variável de instância estática s1 já existia, e seu
valor pode ser acessado independentemente da instância a. Isso você
também já conhece!
Quarto detalhe: Esse é legal! Se você criar Strings sem utilizar o
comando new, e essas Strings possuírem o mesmo valor, por exemplo
"Guilherme", o JVM só instancia uma String e todas as variáveis de
instância referenciam esse objeto. Não entendi! Seguinte: Observe que s1
possui o valor "Guilherme" e que s2 também possui o valor "Guilherme".
Pelo fato do valor "Guilherme" ser o mesmo para ambas variáveis, o JVM
instância um único objeto e s1 e s2 apontam para ele. Isso também é
válido para s3. Porque ocorre isso? Não está claro! Se fossem 2000
variáveis de instância s's apontando para o mesmo valor, por que a JVM
gastaria uma cacetada de memória com isso! Já que é o mesmo valor, ela
cria um único objeto e todas as variáveis de instância apontam para ele.
O JVM sabe economizar memória (ainda mais nesses dias de crise
financeira!).
Quinto detalhe: No caso onde s5 recebe s1, os objetos, mais do
que explicitamente, são os mesmos. O mesmo é válido para s6 = a.s2. Isso
significa que a variável de instância s6 está apontando para o mesmo
objeto que a variável de instância a.s2.
Sexto detalhe: Observe que quando s4 recebeu um novo objeto com a
sintaxe "new String(s1)", o termo new foi usado. Desta forma, o JVM é
obrigado a instânciar outra String na memória, mesmo que os valores
sejam iguais. Isso significa que s4 != s1.
Bom, tento ressaltado esses detalhes, vamos ao que interessa: qual será a saída do Test9?
true
true
false
true
true
false
true
true
false
true
true
Se sua saída foi igual à mostrada acima, parabéns! Você está dominando a
instânciação dos objetos, inclusive as particularidades da String.
Ahh... minha saída ficou parecida! Cara, sinceramente, em programação ou
"é" ou "não é"! O "parecida" não vale, pow! ... Bom, se a saída foi
distinta, procure entender o detalhes que discutimos acima e veja a
explicação completa abaixo.
Entendendo o Test9
Vamos lá! s1 recebe o valor "Guilherme". Quando s2 está recebendo o valor "Guilherme", o JVM pensa: perai!
Esse objeto já existe! Eu não vou usar mais espaço para guardar esse
mesmo objeto só porque s2 tá querendo! s2, toma esse objeto mesmo, ele é
igualzinho, ninguém vai reparar! Então s2 recebe o mesmo objeto de s1. Quando s3 é definida com "Guilherme", o JVM, mais uma vez, reflete: Caramba! Esse pessoal tá querendo me sacanear. Vê
só! Outro objeto com esse nome!? Quem é esse tal de Guilherme afinal?
Não estou nem ai! s3 vai receber o mesmo objeto de s1 - ele não vai nem
perceber! Mais uma vez, a variável de instância s3 aponta para o
mesmo objeto de s1. Agora veja o que ocorre na JVM quando s4 recebe uma
nova String: $%#@$! Esse tal de s4 é safado mesmo! Ele sabe que eu já
tenho um objeto "Guilherme" na memória e pediu um novo (new). Não vai
ter jeito, esse ai eu vou ter que criar um novo objeto. s4 toma ai seu
novo objeto "Guilherme" - que pena ele é igualzinho ao outro! Então,
s4 aponta para um outro objeto String. No caso de s5 e s6, eles estão
recebendo a mesma instância de s1 e a.s2, então, obviamente, também
possuem o mesmo objeto.
Vamos às saídas
Em "s1 == a.s2" o resultado é true poque ambos apontam para Guilherme.
Em "s1 == s3", o resultado também é true, pelo mesmo motivo.
Em "s1 == s4", como s4 soliciou uma nova instância com o comando new, a saída é false.
Em "s1 == s5", obviamente, é true.
Em "a.s2 == s3", a saída é true, pois ambos compartilham o mesmo objeto.
Em "a.s2 == s4", o resultado é false.
Em "a.s2 == s5", o resultado é true.
Em "a.s2 == s6", o resultado é true.
Em "s4 == s5", a saída é false, pois s4 pediu um novo objeto.
Em "s1.equals(a.s2)", a saída só poderia ser true, pois s1 == s2, então obrigatoriamente seus valores também são iguais.
Em "s1.equals(s6)", a saída também é true.
Entendeu?!
Bixo! Se tu não entendeu até agora, aconselho ir tirar uma certificação de outra coisa! De tricô, talvez!
Brincadeirinha! Se você ainda não entendeu! Dê uma olhadinha nas
referências deste artigo. Existem muito material legal sobre essas
características na Internet também. Procure no Google e seja feliz!
Qualquer coisa me manda um e-mail.
Referências
http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html
Espero ter ajudado!
Guilherme Pontes
Nenhum comentário:
Postar um comentário