Primeira "Pegadinha"

12 respostas
duardor

Ae galera tenho uma coisa interessante pra mostra aki, e pode cair em provas de certificação…
Assim:

public class compareString{
  
  public static void main(String args[]){
    
    String str1 = "Ola";
    String str2 = "Ola";
    String str3 = new String("Oi");
    String str4 = new String("Oi");
    System.out.println(str1 == str2);
    System.out.println(str3 == str4);
    System.out.println(str1.equals(str2));
    System.out.println(str3.equals(str4));
  }
}

Eh isso ai
Entao o que vcs acham q vai ser impresso… Nao vale compilar e rodar hein!!!
Seria interessante tambem saber o porque dos resultados, eu fiquei surpreso mas depois vi que tava certo pelo modo como java faz a alocação…
Abraços

12 Respostas

R

eu acho q vai dar pau na compilacao dessa linha…

System.out.println(str1 == str2);

falow

boaglio

Confesso que fiz de cabeça e compilei pra conferir…

Essa é pegadinha mesmo, com certeza eu teria errado

:wink:

aleraraujo

Pq ele retorna um boolean nessa linha:

System.out.println(str1 == str2);

[]s

Rafael_Steil

Para quem deve ter feito o teste e nao consegue entender a razao do resultado, a explicacao eh simples:

Em Java, o operador de igualdade ( == ) quando aplicado a objetos, compara as referencias do objeto, e nao a igualdade baseada no conteudo deles. Baseado nisso, se for prestado atencao, alguem poderia dizer: “mas porque entao a comparacao str1 == str2 retorna true???”.
Essa eh uma, digamos assim, regra as excessoes. Objetos do tipo String sao armazenados em um lugar chamdo “pool de string”, que a finalidade basica eh poder realizar algum aproveitamento de memoria no programa.

Quando fazemos

String str1 = "Ola";

a string “ola” eh coloca no pool de strings e tem a sua referencia armazenada na variavel “str1”. Quando o codigo

String str2 = "Ola";

eh executado, o compilador “ve” que ja tem uma string igual no pool de strings e entao, ao inves de criar um novo objeto e associar uma nova referencia a “str2”, ele simplesmente usa a referencia do “Ola” ja existente no pool, economizando assim memoria.
Por serem referencias iguais, a comparacao

str1 == str2

retorna true.
Agora, quando fazemos

String str3 = new String("Oi");
String str4 = new String("Oi");

estamos dizendo ao Java “Java, eu tenho CERTEZA que quero dois objetos diferentes, entao nao use o pool de Strings”, e entao sao criados 2 objetos diferentes, o que resulta em referencias diferentes, levando a comparacao de igualdade retornar false.

As comparacoes usando o metodo “equals” retornam “true” porque este metodo compara o conteudo contido nos objetos, e nao as referencias.
Por isso que dizem que, para verificar se 2 objetos tem conteudos iguais, deve ser usado o metodo “equals”.

Basicamente eh isso :slight_smile:

Rafael

Alexandre

Cara, fiz de cabeça e consegui acertar…
mandem mais se vcs tiverem, poderiamos criar uma parte do forum
especialmente para isso…
ok vcs acham???

Rafael_Steil

O forum de certificacao ja eh um lugar apropriado :slight_smile:
Nada melhor que aqui para discutiir coisas sobre a certificacao, e isso inclui “pegadinhas”.

Rafael

Alexandre

Realmente, vc esta certo!

duardor

Ae galera eu to repassando todo o material q eu tenho aki… quando eu achar algo interessante eu posto aki
Abraços

boaglio

Interessante essa explicação do Rafael, eu não sabia desse comportamento
do JAVA, eu achava que ele daria:

true
true
false
false

Depois eu fiz uma pequena alteração na rotina para fazer
mais um teste:

public class compareString{
 
  public static void main(String args[]){
   
    String str1 = "Ola";
    String str2 = "Ola";
    System.out.println(str1 == str2);
    str2 = "Ola diferente";
    System.out.println(str1 == str2);
  }
}

E deu isso:

true
false

Isso mostra que esse compartamento do JAVA de verificar que
a mesma coisa já foi declarada e tirar proveito disso é
suficientemente inteligente de verificar que a variável foi
alterada e esse “aproveitamento” já não é mais possível.

Interessante…

Bruno_Cardoso

Boas,

Por acaso eu já conhecia esta “ratoeira” mas à pouco tempo voltei a cair numa bastante identica…

public class Teste { static public void main(String[] whatever) { String s = "Ja"; String s1 = s + "va"; String s2 = "Java"; System.out.println(s1 == s2); System.out.println(s1.equals(s2)); } }

qual acham que vai ser o resultado disto?
Já agora reparem na assinatura do metodo main, mta gente pensa que tem que ser sempre public static void main(String[] args) e não é verdade…

PEACE!

T

Bem, lendo os comentários feitos anteriormente à esta sua questão, fica fácil concluir:

Você tem uma instância da String “Ja” e uma outra instância da String “va”, certo? Unindo as duas, você terá uma nova instância cujo conteúdo é “Ja”+“va” = “Java”!
Se a JVM for inteligente, irá procurar se existe uma instância na memória de uma string com esse conteúdo. Como ‘s1’ é contém “Java”, irá utilizar a mesma cópia da string que está na memória.

Logo,
if (s1 == s2); // => true!

Essa seria uma explicação plausível, certo?

Porém, a mesma JVM poderia considerar s2 como sendo uma string ‘dividida’, onde uma parte dela (“Ja”) está em um endereço de memória e a outra parte, em um endereço diferente, o que causaria:

if(s1 == s2); => false!

Quanto à resposta, prefiro acreditar na segunda hipótese!

P

Quando eu uso new Object, ele joga no heap, ou ainda deixa no pool de string? o pool de literal é usado somente para tipos primitivos ou só para númericos?

Criado 28 de fevereiro de 2003
Ultima resposta 22 de mai. de 2004
Respostas 12
Participantes 9