Considere este código:
String first = "abc"; String second = new String("abc");
Ao usar a new
palavra-chave, o Java criará a String
abc
novamente, certo? Isso será armazenado no heap normal ou no pool de String
? Quantos String
s terminará no pool de String
?
Se você usar a new
palavra-chave, um novo object String
será criado. Observe que os objects estão sempre no heap – o conjunto de cadeias não é uma área de memory separada separada do heap.
O pool de strings é como um cache. Se você fizer isto:
String s = "abc"; String p = "abc";
então, o compilador Java é esperto o suficiente para fazer apenas um object String
, e s
e p
estarão se referindo a esse mesmo object String. Se você fizer isto:
String s = new String("abc");
então, haverá um object String
no pool, aquele que representa o literal "abc"
, e haverá um object String
separado, não no pool, que contém uma cópia do conteúdo do object em pool. Como String
é imutável em Java, você não está ganhando nada fazendo isso; Chamar new String("literal")
nunca faz sentido em Java e é desnecessariamente ineficiente.
Note que você pode chamar intern()
em um object String
. Isso colocará o object String
no pool, se ainda não estiver lá, e retornará a referência à string agrupada. (Se já estava no pool, apenas retorna uma referência ao object que já estava lá). Veja a documentação da API para esse método para mais informações.
Veja também String interning (Wikipedia).
No bytecode , a primeira tarefa é:
Código: 0: ldc # 2; // String abc 2: astore_1
enquanto o segundo é:
3: novo # 3; // class java / lang / String 6: dup 7: ldc # 2; // String abc 9: invokespecial # 4; // Método java / lang / String. "" :( Ljava / lang / String;) V
Portanto, o primeiro está no pool (na posição # 2), enquanto o segundo será armazenado no heap.
EDITAR
Como o CONSTANT_String_info
armazena o índice como U2 (16 bits, sem sinal), o conjunto pode conter no máximo 2**16
= 65535
referências. No caso você se importa aqui mais limites da JVM .
Cada vez que seu código cria uma string literal
por exemplo:
String str="Hello"; (string literal)
a JVM verifica primeiro o pool literal de cadeias. Se a cadeia já existir no conjunto, uma referência à instância em pool será retornada. Se a string não existir no pool, um novo object String instanciará e, em seguida, será colocado no pool. Java pode fazer essa otimização, pois as strings são imutáveis e podem ser compartilhadas sem medo de corrupção de dados
String strObject = new String("Java");
e
String strLiteral = "Java";
Ambas as expressões fornecem objects String, mas há uma diferença sutil entre eles. Quando você cria o object String usando o operador new (), ele sempre cria um novo object na memory heap. Por outro lado, se você criar um object usando a syntax literal de string, por exemplo, “Java”, ele pode retornar um object existente do conjunto String (um cache do object String no espaço Perm gen, que agora é movido para o espaço heap na liberação recente do Java) , se já existe.
A única vez que você deve usar o novo String (foo) é quando você quer quebrar ==, o que é um caso estranho, ou quando foo é uma substring de uma string muito maior que tem um tempo de vida limitado, como
String mystring; { String source = getSomeHeinouslyLargeString(); mystring = new String(source.substring(1,3)); }
Embora tarde, pode ser útil para alguém ainda se deparar com isso:
String first = "abc"; //One instance object in pool created. Instance variable “first” refers/points to pooled object String second = new String("abc"); //One instance object in heap created. Object in pool creation step will be skipped on account of first statement.
Então, no total, 2 objects de instância serão criados. Um na piscina e outro na pilha
Explicação detalhada
String primeiro = “abc”;
Aqui um object string com o conteúdo “abc” criado no pool. A variável de instância “primeiro” apontará para o object pool com o conteúdo “abc”.
String second = new String (“abc”);
Aqui outro object de string com conteúdo “abc” será criado na pilha. A variável de instância “second” apontará para o object heap com o conteúdo “abc”. Um object de string com criação de conteúdo “abc” no pool será ignorado na primeira instrução. Razão abaixo.
Motivos
Se a declaração anterior (String first = “abc”) não existir com o mesmo conteúdo, geralmente com a palavra-chave “new”, serão criados dois objects string no heap (pool externo) e o outro no pool (um subconjunto) de heap). Além disso, a variável de instância “second” deve apontar apenas para o object heap, independentemente de os objects estarem no pool ou não.
Agora, por conta da presença de uma instrução anterior (String first = “abc”;) com o mesmo conteúdo da nova String (“abc”), apenas um object (com conteúdo “abc”) é retido no pool. Portanto, por conta da primeira instrução, a segunda instrução terá apenas 1 object criado em vez de 2 e esse object está na pilha. A criação do object de pool será ignorada.
//Additional Test on the concept System.out.println(first==second); //returns false. Because first points to pool object while second points to heap object. And both objects are different (on account of different memory locations). second = second.intern(); //After interning, second now points to pool object. Note: intern is used so that reference variable points to pool area object and not heap object. Clearly it is applicable when we use new keyword. System.out.println(first==second); //returns true. Because now both first and second objects now points to same pool object.
String first = "abc"; String second = new String("abc");
No primeiro caso, apenas um object será criado no Pool. No segundo caso, dois objects criarão um no pool (se isso não existir anteriormente no Pool) e um no heap.
Quando você está passando qualquer valor com aspas duplas ex: “abc” você está criando um object no pool e passando para o construtor de string para criar um novo object com o mesmo valor no heap.
Se você viu o construtor de string, poderá ver que ele aceita uma string. O que é essa cadeia? Antes da criação, o que é esse object de string. Não é nada, mas um object armazenado no pool String Constant.