Pool de Strings

41 respostas
J

Olá pessoal,

Alguem sabe explicar o escopo da permanencia de Strings no pool. Quando exatamente ela vai para o pool e quando ela deixa de existir no pool. Quando posso considerar que uma variavel de referencia irá referenciar uma string do pool ou criará uma nova? A String existirá no pool enquanto existir variaveis lhe referenciando ou mesmo depois de perdida permanecerá no pool?

41 Respostas

B

Todas as Strings declaradas de maneira literal vão para o pool…É uma maneira da JVM otimizar seu desempenho em runtime. Portanto em sua primeira checagem é colocado no pool todas as String de valor literal presentes no momento, e as referências feitas a uma String literal de mesmo valor, vão apontar para a mesma “instância” no pool.

Alguns exemplos simples:

Apenas sendo criada uma instancia de valor “java” no pool…nenhum objeto criado na heap: String str = "java";

Uma string “java” criada no pool e um objeto String na heap:

Se vc fizer isso, as duas variáveis vão apontar para a mesma instância no pool:

String str = "java"; String str1 = "java";

B

Ah sim… Li há um tempo atrás q não é possível saber ao certo quando (ou SE) é feita a limpeza do pool…
Garbage Collector não atua ali.

Por sorte não é um conhecimento necessário para a prova.

J

Caro brrodo,

String str = "java";

Até então pensava que com o literal um novo objeto fosse criado no heap e no pool. É isso mesmo?

No exemplo acima pensava estar sendo criadas dois objetos string no heap onde o literal iria para o pool.

E em relação ao Garage Collector. Como poderei saber quantos objetos String estarão elegiveis ao coletor caso exista a repetição de strings (a reutilização de uma string do pool) se não se pode prever a forma de limpeza deste pool? Ainda não ficou claro para mim.

T

So para deixar bem claro, o código a seguir não cria nada no pool de strings, uma string criada com new so pode fazer parte do pool quando se usa o método intern() para essa string.

Sobre o Garbage Collector, vou dar um pequeno exemplo a seguir

String name = "pato";  
 String sobrenome = "branco";  
 name = "pato branco";

A string pato, após a 3 linha vai ficar legível para o coletor de lixo.
Me corrijam se estiver errado.

B

jbjares:
Caro brrodo,

String str = "java";

Até então pensava que com o literal um novo objeto fosse criado no heap e no pool. É isso mesmo?

Neste caso, nenhum objeto é criado na heap, apenas na pool, e a variável “str” fará referência a ele.
Talvez vc esteja confundindo o comportamento das strings neste caso com um “autoboxing”.

jbjares:

brrodo:

No exemplo acima pensava estar sendo criadas dois objetos string no heap onde o literal iria para o pool.

Já neste caso, a string literal “java” irá para o pool, e um objeto new String(“java”) estará na heap. A variável str fará referência ao objeto na heap.

jbjares:

E em relação ao Garage Collector. Como poderei saber quantos objetos String estarão elegiveis ao coletor caso exista a repetição de strings (a reutilização de uma string do pool) se não se pode prever a forma de limpeza deste pool? Ainda não ficou claro para mim.
[/quote]

Lembre-se que o Garbage Collector só atua na heap. Portanto o que eu quis dizer é q até onde eu sei (…e pelas fontes que consultei), a limpeza do pool não pode ser precisada, ou seja, não há nenhum mecanismo responsável pela limpeza desta área de memória ocupada em específico. Caso alguém saiba mais sobre isso, pode complementar o que eu disse aqui.

Com essas informações acho q já dá pra concluir quais objetos serão, ou não, candidatos ao GC.

Pra complementar esse tema, vale a pena olhar esse post aqui. Uma questão interessante de “Strings in pool”:
http://www.guj.com.br/posts/list/116352.java

T

Se estiver errado me corrijam.

B

taaqui:

Se estiver errado me corrijam.

Desta meneira que vc representou há 2 strings literais “java” no pool.

Na verdade só haverá 1.

T

Acho que não, se fosse assim eu faria

public class Testador {
        public static void main(String[] args) {
        	 String s1 = new String ("abacaxi");  
        	 String s4 = "abacaxi";
        	 System.out.println (s1 == s4);
        	 
		}
}

e teria que dar true por esta referenciando o mesmo id no pool de strings?

B
taaqui:
Acho que não, se fosse assim eu faria
public class Testador {
        public static void main(String[] args) {
        	 String s1 = new String ("abacaxi");  
        	 String s4 = "abacaxi";
        	 System.out.println (s1 == s4);
        	 
		}
}

e teria que dar true por esta referenciando o mesmo id no pool de strings?

Não. Repare q vc está usando o operador "==".

Ele só retornará true caso as duas variáveis comparadas façam referencia ao mesmo objeto...Mas...
s1 se refere a um objeto String na heap.
s2 se refere a uma string literal no pool.
Logo, o retorno será "false".

O que vc tentou fazer na verdade é isso:

public static void main(String[] args) {  
	               String s1 = new String ("abacaxi").intern();    
	               String s4 = "abacaxi";  
	               System.out.println (s1 == s4);  
	                 
	         }

Repare q agora sim a variável s1 recebeu o valor que está na pool...e agora o sim vc verá que a comparação retornará "true", confirmando o q eu disse.

J

Olá Amigos,
Desculpem a demora em responder essa semana está sendo bastante pesada em meu trabalho. Agradeço muito o apoio de brrodo e taaqui, ta bem legal a discussão.
Quando lí essa mesma parte do livro da K.Sierra que o brrodo citou eu entendi que dois objetos String são criados sendo que o mais interno, o que é passado como argumento ao construtor da classe String irá para o pool, por se tratar de um literal, mas em nenhum momento eu havia lido sobre esse detalhe de que só os literais vão para o pool ou que não são criados objetos no heap para estes. Para mim ainda não está claro.

Achei inclusive bastante interessante aquela discussão que o brrodo citou aqui no forum da questão do testkiller. Para mim aquela questão está mal elaborada… Eu entendi que são criadas 5 Objetos String sendo que de certeza mesmo caso “Fred” e “47” já estivessem no pool só foram criadas 3. Então no meu ponto de vista a pergunta deveria ser: “Quantos objetos String serão criados COM CERTEZA quando este método for chamado?” Aí sim a resposta seria 3. letra C.

1. Given:   
   2. 11. public String makinStrings() {   
   3. 12. String s = ?Fred?;  // Crio a String  "Fred"  
   4. 13. s = s + ?47?;        // Criou a string 47 e depois criou a String Fred47, até aqui  são 3.
   5. 14. s = s.substring(2, 5); // 4 outra String criada. 
   6. 15. s = s.toUpperCase(); // 5 mais uma String criada.
   7. 16. return s.toString();    // retornou a string referenciada por s (não criou nada).
   8. 17. }   
   9. How many String objects will be created when this method is invoked?   
  10. A. 1   
  11. B. 2   
  12. C. 3   
  13. D. 4   
  14. E. 5   
  15. F. 6

O que vocês acham??

T

Também estou com um merda de um mosquito zunindo no meu ouvido sobre isso, então vamos la, para onde vai o literal criado no objeto String s1 = new String (“abacaxi”);? para o pool certo? então como String s4 = "abacaxi"; ja se encontra no pool ele vai referencia o abacaxi ja criado no pool?

olha a figura
Ps: adorei fazer essas coisas ^^

J

AUhuaUHAUhaUHUA :slight_smile: Esses gráficos são bem legais mesmo taaqui…

Cara,

Vamos pegar a explicação da K.Sierra a respeito da criação de String. Comentarei os pontos críticos com (A,B,C,D…) para analisarmos melhor um a um.

A) Um novo Objeto String é criado.
B) “abc” vai para o pool e “s” o referenciará. Então podemos pensar no pool de String como sendo um pool de objetos String e não em um pool de literais, Certo?
C) São criados dois Objetos String.
D) Por utilizar a palavra-chave new será criado um Objeto String no Heap e “s” o referenciará.
E) Adicionalmente o literal “abc” será inserido no pool. Neste ponto a coisa se complica. A lógica do tópico B) é exterminada quando ela diz que o literal “abc” vai para o pool, concorda? Então de que é composto esse pool, de Objetos ou literais? Caso ele seja composto por literais oque acontece com o Objeto criado no tópico A)? O lugar dos novos objetos não é o Heap? Então no tópico A) é criado um novo Objeto String que vai para o Heap e um literal que vai para o pool, mas a variável referencia o literal do pool no lugar do Objeto que foi para o Heap?

Está lançado o desafio. Vamos desmistificar de uma vez por todas aqui no GUJ o que de fato acontece no momento da criação de Strings!!!

B

jbjares:
AUhuaUHAUhaUHUA :slight_smile: Esses gráficos são bem legais mesmo taaqui…

Cara,

Vamos pegar a explicação da K.Sierra a respeito da criação de String. Comentarei os pontos críticos com (A,B,C,D…) para analisarmos melhor um a um.

A) Um novo Objeto String é criado.
B) “abc” vai para o pool e “s” o referenciará. Então podemos pensar no pool de String como sendo um pool de objetos String e não em um pool de literais, Certo?
C) São criados dois Objetos String.
D) Por utilizar a palavra-chave new será criado um Objeto String no Heap e “s” o referenciará.
E) Adicionalmente o literal “abc” será inserido no pool. Neste ponto a coisa se complica. A lógica do tópico B) é exterminada quando ela diz que o literal “abc” vai para o pool, concorda? Então de que é composto esse pool, de Objetos ou literais? Caso ele seja composto por literais oque acontece com o Objeto criado no tópico A)? O lugar dos novos objetos não é o Heap? Então no tópico A) é criado um novo Objeto String que vai para o Heap e um literal que vai para o pool, mas a variável referencia o literal do pool no lugar do Objeto que foi para o Heap?

Está lançado o desafio. Vamos desmistificar de uma vez por todas aqui no GUJ o que de fato acontece no momento da criação de Strings!!!

taaqui agora está certo. :slight_smile:

jbjares, eu acho q essas dúvidas q vc teve agora já foram explicadas nos posts anteriores. Em A) é criado um “objeto” (entre aspas, pois vc está sempre vinculando objeto à heap, mas não é este o caso aqui) no pool apenas, nada é feito na heap.

jbjares, o gráfico do taaqui agora está correto, se olhar ele, vai entender melhor o q acontece em E).

…e lembre-se que não há como o pool ser afetado pelo GC.

J

Caro brrodo,

Concordo que o exemplo do taaqui está coerente. É isso mesmo! Valeu pessoal.

J

Só para finalizar vou postar aqui o link da JLS (Java Language Specification) Melhor que isso é impossivel. Daí cada um tira suas próprias conclusões. :slight_smile:

Eu entendi que o pool é um lugar onde guarda literais que referenciam Objetos no Heap. Quando uma String é criada assim: String s = “teste”; É criado um objeto no Heap e um literal no pool que aponta para este objeto. Quando é Criado uma String assim String str = new String(“teste”); São criados dois objetos String contendo o mesmo valor e “teste” vai pro Heap também porem caso exista “teste” no Heap o meu Objeto String criado continuará criando dois objetos String. Enfim, o meu entendimento é este baseado na JLS. Aconselho a cada que tenha a mesma dúvida ir direto na fonte e não ficar tentando adivinhar porque pode se dar mal.

JLS: http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5

Valeu Pessoal!

J

Só para finalizar vou postar aqui o link da JLS (Java Language Specification) Melhor que isso é impossivel. Daí cada um tira suas próprias conclusões.

Eu entendi que o pool é um lugar onde guarda literais que referenciam Objetos no Heap. Quando uma String é criada assim: String s = “teste”; É criado um objeto no Heap e um literal no pool que aponta para este objeto. Quando é Criado uma String assim String str = new String(“teste”); São criados dois objetos String contendo o mesmo valor e “teste” vai pro Heap também porem caso exista “teste” no Heap o meu Objeto String criado continuará criando dois objetos String. Enfim, o meu entendimento é este baseado na JLS. Aconselho a cada que tenha a mesma dúvida ir direto na fonte e não ficar tentando adivinhar porque pode se dar mal.

JLS: http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5

Valeu Pessoal!

O

Caros amigos. Como tambem estou estudando para SCJP e nesse caso eu me confundi todo com base nos dois posts indicados aqui na discussao. Gostaria que voces me ajudassem.

Como foi discutido no post que brrodo passou como referencia gostaria que voces me ajudassem a entender.

Quando eu tenho esse trecho quantos OBJETOS são criados? Levando em consideração as explicações passadas e cada trecho esta separado:

String s1 = "fred";

Com base na explicação nao é criado nenhum OBJETO (propriamente dito), ja que nesse caso levamos em consideração que como é uma literal o valor (“fred”) seria lancado para o pool e nao para o heap como um objeto?

E quando temos assim:

String s2 = new String("fred");

Ae teriamos um OBJETO no heap e um objetinho no poll?

Agora se tivessemos esses trechos juntos no mesmo arquivo:

String s1 = "fred";
String s2 = new String("fred");

Teriamos ainda um OBJETO apenas. Estou confuso. Ainda mais com a formulacao das perguntas da prova…

O que voces acham?

B

omaisnormalbaba, é isso mesmo.

O

brrodo

Entao quer dizer que se tivesse uma pergunta querendo saber quantos objetos foram criados seguindo este trecho qual seria a resposta?

public void testeString() {
		String s1 = "fred";
		String s2 = new String("marcos");
		String s3 = new String("fred");
		s1 = s1.concat(" silva"); // aqui eu travei,
		String s4 = s1;
}

Qual seria a resposta? Na minha concepcao sera 3. Estou certo?

T

omaisnormalbaba:
Caros amigos. Como tambem estou estudando para SCJP e nesse caso eu me confundi todo com base nos dois posts indicados aqui na discussao. Gostaria que voces me ajudassem.

Como foi discutido no post que brrodo passou como referencia gostaria que voces me ajudassem a entender.

Quando eu tenho esse trecho quantos OBJETOS são criados? Levando em consideração as explicações passadas e cada trecho esta separado:

String s1 = "fred";

Com base na explicação nao é criado nenhum OBJETO (propriamente dito), ja que nesse caso levamos em consideração que como é uma literal o valor (“fred”) seria lancado para o pool e nao para o heap como um objeto?

E quando temos assim:

String s2 = new String("fred");

Ae teriamos um OBJETO no heap e um objetinho no poll?

Agora se tivessemos esses trechos juntos no mesmo arquivo:

String s1 = "fred";
String s2 = new String("fred");

Teriamos ainda um OBJETO apenas. Estou confuso. Ainda mais com a formulacao das perguntas da prova…

O que voces acham?

É isso mesmo, veja a figura que passei no post anterior.

public void testeString() { String s1 = "fred"; // Cria o s1, literal no pool de strings String s2 = new String("marcos"); // cria o s2, objeto no heap referenciando "marcos" no pool de strings String s3 = new String("fred"); // cria o s3, objeto no heap referenciando "fred" no pool de strings. s1 = s1.concat(" silva"); // faz s1 com o literal "fred" morrer e passa a referencia a concatenação "fred silva", mais não cria nenhum objeto. String s4 = s1; // cria s4 e referencia s1, que agora deixou o "fred" no pool de strings para criar o "fred silva". }

fato que s1 e s4 referenciam o mesmo literal no pool, ou seja soh 3 literais estão no pool de strings e no heap é criado soh 2 objetos.
Se eu estiver errado me corrijam.

B

Eita, ta rendendo esse assunto ehehehe. Vamo lá:

public void testeString() { String s1 = "fred"; //Pega a literal "fred" do pool e referencia s1 a ela. String s2 = new String("marcos"); //Primeiro objeto criado e "marcos" no pool. String s3 = new String("fred"); // Segundo objeto criado. "fred" JÁ está no pool (ver s1). s1 = s1.concat(" silva"); // Terceiro objeto criado ("fred silva")... e "silva" no pool. String s4 = s1; }

3 objetos criados. 3 literais no pool.
Pode-se dizer assim.

O

brrodo:
Eita, ta rendendo esse assunto ehehehe. Vamo lá:

public void testeString() { String s1 = "fred"; //Pega a literal "fred" do pool e referencia s1 a ela. String s2 = new String("marcos"); //Primeiro objeto criado e "marcos" no pool. String s3 = new String("fred"); // Segundo objeto criado. "fred" JÁ está no pool (ver s1). s1 = s1.concat(" silva"); // Terceiro objeto criado ("fred silva")... e "silva" no pool. String s4 = s1; }

3 objetos criados. 3 literais no pool.
Pode-se dizer assim.

To adorando isso…

Esse novo String criado (fred silva) nao deveria estar no pool ao inves de (silva)? Ja que ele sera um novo objeto criado;…

B

omaisnormalbaba:
brrodo:
Eita, ta rendendo esse assunto ehehehe. Vamo lá:

public void testeString() { String s1 = "fred"; //Pega a literal "fred" do pool e referencia s1 a ela. String s2 = new String("marcos"); //Primeiro objeto criado e "marcos" no pool. String s3 = new String("fred"); // Segundo objeto criado. "fred" JÁ está no pool (ver s1). s1 = s1.concat(" silva"); // Terceiro objeto criado ("fred silva")... e "silva" no pool. String s4 = s1; }

3 objetos criados. 3 literais no pool.
Pode-se dizer assim.

To adorando isso…

Esse novo String criado (fred silva) nao deveria estar no pool ao inves de (silva)? Ja que ele sera um novo objeto criado;…

Entenda q o pool de strings é populado ANTES do código ser executado…As únicas strings literais existentes até este ponto são:
“fred”
“marcos”
" silva"

O intuito do pool é otimizar o desempenho da JVM, da seguinte maneira:
Varrer o código e separar todas as literais declaradas e checar se, por exemplo, existem 2 ou mais string literais “fred” declaradas no código (como no caso q vc citou), se houver, apenas uma string será coloada no pool e todas as referências apontarão pra ela. É uma maneira de “poupar” memória.

No caso do String.concat(), se puder olhar na documentação verá q ela retorna um objeto String.

Espero q tenha ficado claro agora.

O

Perfect!!!

Agora iluminou tudo.

Obrigado pessoal.

J

Caro taaqui e brrodo,

Acho importante que este tema esteja rendendo :slight_smile: E eu vou colocar mais lenha na fogueira porque meu entendimento não bate com o seu. E para dar credibilidade a minha análise me basearei na
JLS (Java Language Specification) onde de fato cada um poderá ir (através do link :http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5) e tirar suas próprias conclusões. Porque já vi gente aquí no GUJ dizendo a JVM no momento em que uma classe é carregada procura todos os literais de String e coloca-os no pool, sinceramente não sei de onde isso foi tirado, eu jamais li nada semelhante em lugar nenhum. Então lá vai:

// Considerando que não existe nada no pool de String:

    public void testeString() {    
      String s1 = "fred";   // Cria um Objeto String no Heap e coloca o literal "fred" no pool apontando para o objeto que está no Heap.  -------------> Primeiro Objeto criado.
      String s2 = new String("marcos");  //Cria dois objetos String um para o new String e outro para "marcos" e insere "marcos" no pool.  -------------> Segundo e Terceiro Objetos criados
      String s3 = new String("fred");   // Cria novamente mais dois objetos como acima desta vez fred não vai mais para o pool, ele já esta lá. -------------> Quarto e Quinto Objeto criado
      s1 = s1.concat(" silva"); // E por fim mais dois Objetos String criados: " silva" e "fred silva" ambos vão para o Heap e para o pool.  -------------> Sexto e sétimo Objeto criado.
      String s4 = s1;    
    }

7 objetos criados. 4 literais no pool.
É meu ponto de vista baseado na seguinte lógica:

Concluo aqui que todo literal referencia um Objeto String no Heap (Afinal é no Heap que os Objetos residem.) então se existe um literal também existe um Objeto String que ele referencia.
Então de acordo com a explicação do brrodo.

Quando foi inserido o literal "fread" no pool para que ele seja pego agora, brrodo? Para mim o literal "fred" é inserido no pool (agora) e também é criado um Objeto no Heap, baseada na afirmação acima.

Ao meu ver são dois novos objetos criados e inseridos no pool.

Baseado na citação acima concluo que new String() é um novo Objeto String criado e "marcos" passado como argumento ao construtor de String é um outro Objeto, já que literais são referencias a instancias da classe String. e o mesmo se aplica para a linha de código da citação abaixo:

E para finalizar:

Chamo aqui mais uma vez a documentação da JSL

Então nesse trecho de código são criados mais dois Objetos " silva" e "fred silva".

Mas essa é minha interpretação baseada na documentação da especificação da linguagem Java. Aconselho a cada um ir na fonte e tirar suas próprias conclusões. :slight_smile:

Boa Sorte a Todos!!

J

Caro brrodo,

Quero só que você me diga de onde tirou esta informação??

Como disse anteriormente, eu jamais lí nada parecido em lugar algum. Quer dizer que a Maquina Virutal tem uma espécie de Thread (serviço) que fica varrendo o código o tempo todo para encontrar “literais” e coloca-los no pool? Cara se vocẽ me disser em que lugar da especificação posso encontrar isso, eu realmente terei que rever meus conceitos. :slight_smile:

T

Quando a JVM carrega uma classe, ela inspeciona as constantes strings que estão definidas no código dessa classe e as “interna” no pool.
Uma classe é carregada quando um objeto dessa classe é criado, ou quando se chama um método estático dessa classe, ou então quando se tenta obter uma referência à classe com Class.forName, ou então quando uma subclasse dessa classe é carregada. Se a classe já estiver carregada por um determinado classloader, normalmente ela não será novamente carregada pelo mesmo classloader, sendo reusada a sua referência.

B

jbjares:
Caro brrodo,

Quero só que você me diga de onde tirou esta informação??

Como disse anteriormente, eu jamais lí nada parecido em lugar algum. Quer dizer que a Maquina Virutal tem uma espécie de Thread (serviço) que fica varrendo o código o tempo todo para encontrar “literais” e coloca-los no pool? Cara se vocẽ me disser em que lugar da especificação posso encontrar isso, eu realmente terei que rever meus conceitos. :slight_smile:

Tentei ser o mais simples possível para q o funcionamento PRÁTICO do “mecanismo” fosse entendido.

Se for no post q citei onde há uma discussão sobre pool de Strings (http://www.guj.com.br/posts/list/116352.java), verá q esta informação é repassada por mais usuários e moderadores.

O próprio livro da Kathy o explica de forma superficial. Além de fontes citadas em fóruns como o JavaRanch. Ou seja, vc poderá encontrar fontes oficiais q o confirmem facilmente se procurar.

Acho q está havendo muitas discordâncias sobre o assunto, e com todo respeito, jbjares, devo lhe dizer q sua conclusão de 7 objetos criados no código acima, está equivocada. Não q a JLS esteja errada, mas acho q sua interpretação do conteúdo lá presente talvez tenha sido feita de maneira incorreta.

Prefiro então deixar q daqui pra frente algum moderador assuma o rumo do tópico pra evitar discordâncias dessa natureza.

J

Poisé no meu ponto de vista aquela discussão só foi encerrada porque todos concordaram com a explicação de que a Maquina Virtual carrega todos os literais de String no pool quando a class é carregada, e não significa que os moderadores e mais de uma pessoa tenham razão podem até ter e se for isso mesmo eu também quero concordar. Mas eu preciso saber onde na especificação da linguagem está essa informação. Só isso, daí eu estarei convencido e o assunto definitivamente encerrado. :slight_smile:

Abraço.

B

jbjares:
Caro brrodo,

Quero só que você me diga de onde tirou esta informação??

Como disse anteriormente, eu jamais lí nada parecido em lugar algum. Quer dizer que a Maquina Virutal tem uma espécie de Thread (serviço) que fica varrendo o código o tempo todo para encontrar “literais” e coloca-los no pool? Cara se vocẽ me disser em que lugar da especificação posso encontrar isso, eu realmente terei que rever meus conceitos. :slight_smile:

Tentei ser o mais simples possível para q o funcionamento PRÁTICO do “mecanismo” fosse entendido.

Se for no post q citei onde há uma discussão sobre pool de Strings (http://www.guj.com.br/posts/list/116352.java), verá q esta informação é repassada por mais usuários e moderadores.

O próprio livro da Kathy o explica de forma superficial. Além de fontes citadas em fóruns como o JavaRanch. Ou seja, vc poderá encontrar fontes oficiais q o confirmem facilmente se procurar.

Acho q está havendo muitas discordâncias sobre o assunto, e com todo respeito, jbjares, devo lhe dizer q sua conclusão de 7 objetos criados no código acima, está equivocada. Não q a JLS esteja errada, mas acho q sua interpretação do conteúdo lá presente talvez tenha sido feita de maneira incorreta.

Prefiro então deixar q daqui pra frente algum moderador (ou quem estiver disposto) assuma o rumo do tópico pra evitar discordâncias dessa natureza.

J

Caro thingol,

Onde consigo esta informação? Quero de uma vez por todas fechar este assunto e deixar meu entendimento neste tema redondo, mas eu preciso de fontes. Vocẽ tem?

Abraço.

T
1. public void testeString() {  
   2.         String s1 = "fred";  
   3.         String s2 = new String("marcos");  
   4.         String s3 = new String("fred");  
   5.         s1 = s1.concat(" silva"); // aqui eu travei,  
   6.         String s4 = s1;  
   7. }

a) Quando a classe que contém este código for carregada, então a JVM irá verificar que há as seguintes constantes string: “fred”, “marcos” e " silva", irá criar um objeto String para cada uma dessas constantes, e irá internar esses tais objetos no pool de strings. Isso, nas questões de provas, não conta como criação de objetos, porque nas provas pergunta-se qual é o número de objetos criados DENTRO do método.
b) Linha 2 - a variável s1 recebe uma referência para o objeto String “fred” que já está no pool. Criados ZERO objetos.
c) Linha 3 - o construtor de String recebe uma referência para o objeto String “marcos” e CRIA UMA NOVA STRING. s2 recebe uma referência para essa nova string. Criado UM objeto (sem contar o objeto char[] que todo objeto String referencia.)
d) Linha 4 - análogo à linha 3. Criado UM objeto.
e) Linha 5 - O método “concat” da classe String, chamado sobre o objeto String contendo o valor “fred”, recebe uma referência para o objeto String " silva", cria um StringBuilder, copia os caracteres contidos nela mesma (“fred”), copia os caracteres contidos no parâmetro (" silva"), e a seguir chama o método toString da classe StringBuilder, o que como resultado líquido CRIA UMA NOVA STRING com o conteúdo “fred silva”. Então essa nova string é atribuída à variável s1, que por sua vez perde referência à string “fred”. Portanto: criado UM objeto. (as questões normalmente só contam o número de objetos líquidos, não os objetos temporários criados pelos métodos).
f) Linha 6 - a variável s4 recebe uma referência ao objeto “fred silva” que também é referido por s1. Criados ZERO objetos.

Portanto foram criados 3 objetos.

T

jbjares:
Caro thingol,

Onde consigo esta informação? Quero de uma vez por todas fechar este assunto e deixar meu entendimento neste tema redondo, mas eu preciso de fontes. Vocẽ tem?

Abraço.

http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html

Cuidado: está escrito em língua de advogado. Não espere entender tudo numa primeira lida.

T
thingol:
1. public void testeString() {  
   2.         String s1 = "fred";  
   3.         String s2 = new String("marcos");  
   4.         String s3 = new String("fred");  
   5.         s1 = s1.concat(" silva"); // aqui eu travei,  
   6.         String s4 = s1;  
   7. }
a) Quando a classe que contém este código for carregada, então a JVM irá verificar que há as seguintes constantes string: "fred", "marcos" e " silva", irá criar um objeto String para cada uma dessas constantes, e irá internar esses tais objetos no pool de strings. Isso, nas questões de provas, não conta como criação de objetos, porque nas provas pergunta-se qual é o número de objetos criados DENTRO do método. b) Linha 2 - a variável s1 recebe uma referência para o objeto String "fred" que já está no pool. Criados ZERO objetos. c) Linha 3 - o construtor de String recebe uma referência para o objeto String "marcos" e CRIA UMA NOVA STRING. s2 recebe uma referência para essa nova string. Criado UM objeto (sem contar o objeto char[] que todo objeto String referencia.) d) Linha 4 - análogo à linha 3. Criado UM objeto. e) Linha 5 - O método "concat" da classe String, chamado sobre o objeto String contendo o valor "fred", recebe uma referência para o objeto String " silva", cria um StringBuilder, copia os caracteres contidos nela mesma ("fred"), copia os caracteres contidos no parâmetro (" silva"), e a seguir chama o método toString da classe StringBuilder, o que como resultado líquido CRIA UMA NOVA STRING com o conteúdo "fred silva". Então essa nova string é atribuída à variável s1, que por sua vez perde referência à string "fred". Portanto: criado UM objeto. (as questões normalmente só contam o número de objetos líquidos, não os objetos temporários criados pelos métodos). f) Linha 6 - a variável s4 recebe uma referência ao objeto "fred silva" que também é referido por s1. Criados ZERO objetos.

Portanto foram criados 3 objetos.

Isso,quase igual a minha explicação de cima^^,
s1 = s1.concat(" silva"); tinha esquecido que criava um objeto..
que bom que foi tudo resolvido...^^
sonhar custa nada...

J

Olá Pessoal,
Muito boa sua explicação thingol. Agooora SIM! :slight_smile: Podemos todos durmir felizes AUhuHAUhAUHUah :slight_smile:
Lí a especificação que você passou e realmente agora tudo faz sentido. Agradeço aos amigos brrodo e taaqui pela participação e apoio, batemos bastante a cabeça mas valeu a pena.

Abraço.

O

Amigos.

Com base nessa discussao amigavel que nós estamos tento eu andei procurando com mais calma aqui na minha casa e encontrei várias respostas a respeito do velho assunto que ja ate se popularizou no javarunch de nome (Fred47)…heheheeh…

Com base nos links que encontrei e as respostas do pessoal eu tive a minha conclusão.

Primeiramente : A pergunta é : Quantos objetos são criados no momento da execução desse método?

Quando uma classe é carregada e COMPILADA as String’s literais são criadas dentro do pool de constantes Strings, isso para economizar memoria isso em tempo de compilação.

Quando o método é chamado (EXECUTADO) a String literal ja se encontra no pool e não é criado nenhum OBJETO. Ou seja, todas as String’s literais em tempo de compilação são criadas e armazenadas no poll de constantes.

Com base nessas afirmações os unicos OBJETOS criados durante a EXECUÇÃO do método são:

String s = ?Fred?;   // "Fred" created at compile time as it is literal.  
s = s + ?47?;  // "47" created at compile time. First object "Fred47" created at runtime when you call this method.  
s = s.substring(2, 5); //second object "ed4" at runtime when you call this method  
s = s.toUpperCase(); //third object "ED4" at runtime when you call this method

Referencia:

http://www.coderanch.com/t/268070/Programmer-Certification-SCJP/certification/Strings

Melhorando ainda mais o POST. Agora colocando o GC. Voces sabem quais objetos estaram aptos para serem excluidos pelo GB?
Na minha opinião esta:

Os objetos “Fred47” e “ed4” estao aptos a serem excluidos pelo GC quando a execucao estiver em return…

O que acham?

J

é isso aí… concordo… :slight_smile: Nota 10 omaisnormalbaba.

V

Não entendo pq se dá tanta relevância a esse tema, se nunca vi uma aplicação em que o conhecimento disso a melhorasse, ou evitasse que você caísse numa armadilha. É só pra agradar os certificadores, mesmo.

Claro, a única coisa relevante disso, é saber que as vezes uma comparação com == pode dar true para strings iguais, mas que isso nem sempre será verdade e que, portanto, o equals deverá ser usado, como você já faria para qualquer objeto.

Mas observado esse detalhe, não sei porque perde-se tanto tempo estudando cada meandro do Pool de strings.

Contar quantos objetos foram criados? Francamente, parece gasto de tempo e esforço demais, para uma curiosidade interessante da linguagem…

É por essas e outras que realmente questiono a qualidade dessas provas de certificação. Temos um candidato que sabe exatamente como funciona cada vírgula do compilador, mas codifica de maneira mal, porca e inenteligível, como os códigos que ele vê nas provas e nos livros da Kathy.

T

ViniGodoy:

Contar quantos objetos foram criados? Francamente, parece gasto de tempo e esforço demais, para uma curiosidade interessante da linguagem…

É por essas e outras que realmente questiono a qualidade dessas provas de certificação. Temos um candidato que sabe exatamente como funciona cada vírgula do compilador, mas codifica de maneira mal, porca e inenteligível, como os códigos que ele vê nas provas e nos livros da Kathy.

+1

B

ViniGodoy:
Não entendo pq se dá tanta relevância a esse tema, se nunca vi uma aplicação em que o conhecimento disso a melhorasse, ou evitasse que você caísse numa armadilha. É só pra agradar os certificadores, mesmo.

Claro, a única coisa relevante disso, é saber que as vezes uma comparação com == pode dar true para strings iguais, mas que isso nem sempre será verdade e que, portanto, o equals deverá ser usado, como você já faria para qualquer objeto.

Mas observado esse detalhe, não sei porque perde-se tanto tempo estudando cada meandro do Pool de strings.

Contar quantos objetos foram criados? Francamente, parece gasto de tempo e esforço demais, para uma curiosidade interessante da linguagem…

É por essas e outras que realmente questiono a qualidade dessas provas de certificação. Temos um candidato que sabe exatamente como funciona cada vírgula do compilador, mas codifica de maneira mal, porca e inenteligível, como os códigos que ele vê nas provas e nos livros da Kathy.

Eu tbm concordo…Mas é mto radical analisar dessa forma.

Trabalho com Java já faz tempo e dá pra dizer q 70% das coisas q vc aprende estudando pra certificação não te faz tornar um melhor desenvolvedor ou analista, mas sim te torna um bom conhecedor da linguagem Java.
Ter certificação sem experiência realmente não vale nada. O que adianta conhecer “cada vírgula da linguagem” se vc não sabe nada de MVC, design patterns e etc!?

Agora se vc agrega certificações a um currículo experiente, é ponto a mais pra vc. Poder dizer q é “reconhecido” pela Sun, pesa. O tal “conhecimento formal” q a grande maioria das empresas valoriza.

T

Eu fiz uma prova de SCJP 5 e posso dizer que tais questões de pool de strings não caem (ou se caem é só umazinha).
De qualquer maneira, acho incrível a quantidade de tempo que se gasta tentando estudar essas coisas, quando outras coisas caem mais e são mais importantes.
Por exemplo, a parte de serialização cai bastante e, na prática, é muito importante para diagnosticar alguns problemas que ocorrem em application servers.

Criado 16 de março de 2009
Ultima resposta 20 de mar. de 2009
Respostas 41
Participantes 6