Pergunta

De acordo com a String # estagiário ( ) , método intern é suposto para retornar a string a partir do pool de cordas Se a string é encontrado em Cadeia piscina, caso contrário, um novo objeto string será adicionado na Cadeia piscina ea referência desta string é retornado.

Então, eu tentei o seguinte:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

Eu estava esperando que s1 and s3 are same será impressa como s3 está internada, e s1 and s2 are same não será impressa. Mas o resultado é: ambas as linhas são impressas. Então isso significa que, por padrão constantes da corda estão internados. Mas se é assim, então por que precisamos do método intern? Em outras palavras, quando devemos usar este método?

Foi útil?

Solução

Java estagiários automaticamente Strings. Isto significa que, em muitos casos, aparece operador == para trabalhar para Cordas da mesma maneira que ele faz para ints ou outros valores primitivos.

Desde internar é automática para literais de string, o método intern() é para ser usado em cordas construído com new String()

Usando o seu exemplo:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

if ( s1 == s4 ){
    System.out.println("s1 and s4 are same" );  // 3.
}

if ( s1 == s5 ){
    System.out.println("s1 and s5 are same" );  // 4.
}

retornará:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

Consulte JavaTechniques "String Igualdade e Internar" para obter mais informações.

Outras dicas

Em um projeto recente, algumas estruturas de dados enormes foram criadas com os dados que foram lidos a partir de um banco de dados (e, portanto, não corda constantes / literais), mas com uma enorme quantidade de duplicação. Foi um aplicativo bancário, e coisas como os nomes de um conjunto modesto (talvez 100 ou 200) Sociedades apareceu em todo o lugar. As estruturas de dados já eram grandes, e se todos esses nomes corp tinha sido objetos únicos que teriam de memória com capacidade excedida. Em vez disso, todas as estruturas de dados tinha referências para o mesmo 100 ou 200 objetos String, poupando assim muito espaço.

Outra pequena vantagem de Cordas internado é que == pode ser usado (com sucesso!) Para comparar strings, se todas as cadeias envolvidas são garantidos para ser internado. Além da sintaxe mais magro, esta é também uma melhoria de desempenho. Mas como outros já apontaram, fazendo isso portos um grande risco de introdução de erros de programação, então isso deve ser feito apenas como uma medida desesperada de último recurso.

A desvantagem é que internar uma String leva mais tempo do que simplesmente jogá-lo na pilha, e que o espaço para Cordas internado pode ser limitada, dependendo da implementação Java. É o melhor feito quando você está lidando com um número razoável conhecida de Cordas com muitas duplicações.

Eu quero adicionar meus 2 centavos sobre o uso == com cordas internados.

A primeira coisa que faz é String.equals this==object.

Assim, embora haja algum ganho de desempenho minúsculo (você não está chamando um método), a partir do ponto de vista mantenedor usando == é um pesadelo, porque algumas cordas internados têm uma tendência a tornar-se não-internado.

Por isso, sugiro não confiar em caso especial de == para cordas internados, mas sempre usar equals como Gosling pretendido.

EDIT: internado se tornar não-internado:

V1.0
public class MyClass
{
  private String reference_val;

  ...

  private boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

Na versão 2.0 mantenedor decidiu tornar pública hasReferenceVal, sem entrar em muitos detalhes que espera uma matriz de strings internados.

V2.0
public class MyClass
{
  private String reference_val;

  ...

  public boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

Agora você tem um bug, que podem ser muito difíceis de encontrar, porque na maioria dos casos matriz contém valores literais, e às vezes uma string não-literal é usado. Se equals foram usados ??em vez de == então hasReferenceVal teria ainda continuar a trabalhar. Mais uma vez, ganho de desempenho é minúsculo, mas o custo de manutenção é alto.

literais e constantes cadeia de caracteres são internadas por padrão. Ou seja, "foo" == "foo" (declarado pelos literais String), mas new String("foo") != new String("foo").

Saiba Java Cordas Intern - uma vez por todas

Strings em Java são objetos imutáveis ??por design. Portanto, dois objetos string, mesmo com o mesmo valor será diferentes objetos por padrão. No entanto, se quisermos salvar a memória, que poderia indicar a utilização mesma memória por um conceito chamado de seqüência interno

A seguir regras que ajudam a entender o conceito em termos claros:.

  1. classe String mantém um estagiário-piscina, que é inicialmente vazio. Esta piscina deve garantir para conter objetos string com apenas valores únicos.
  2. Todas as strings literais tendo mesmo valor deve ser considerado mesmo objeto memória de localização, porque eles têm outra forma nenhuma noção de distinção. Portanto, todos esses literais com o mesmo valor fará uma única entrada na estagiário-piscina e irá se referir a mesma posição de memória.
  3. A concatenação de duas ou mais literais também é um literal. (Portanto regra # 2 será aplicável para eles)
  4. Cada corda criado como objeto (ou seja por qualquer outro método exceto como literal) terá posições de memória diferentes e não vai fazer qualquer entrada na estagiário-pool
  5. A concatenação de literais com não-literais fará um não-literal. Assim, o objeto resultante terá um novo local de memória e não fará uma entrada no estagiário-piscina.
  6. invocando o método interno em um objeto string, ou cria um novo objeto que entra o estagiário-piscina ou retornar um objeto existente a partir da piscina que tem mesmo valor. A invocação em qualquer objeto que não está no estagiário-piscina, não se move o objeto para a piscina. É algo que cria outro objeto que entra na piscina.

Exemplo:

String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2)  //would return false  by rule #4
If (“abc” == “a”+”bc” )  //would return true by rules #2 and #3
If (“abc” == s1 )  //would return false  by rules #1,2 and #4
If (“abc” == s1.intern() )  //would return true  by rules #1,2,4 and #6
If ( s1 == s2.intern() )      //wound return false by rules #1,4, and #6

Nota: Os casos motivacionais para estagiário cadeia não são discutidos aqui. No entanto, economizando de memória será definitivamente um dos objectivos primários.

você deve fazer para fora duas vezes período que são tempo de compilação e tempo de execução time.for exemplo:

//example 1 
"test" == "test" // --> true 
"test" == "te" + "st" // --> true

//example 2 
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true

em um lado, no exemplo 1, encontramos os resultados são todos return true, porque no tempo de compilação, a JVM vai colocar o "teste" para o conjunto de strings literais, se a JVM find "teste" existe, então ele usará o existe um, no exemplo 1, as cordas "testar" são todos apontam para o mesmo endereço de memória, de modo que o exemplo 1 retornará verdadeiro. no outro lado, no exemplo 2, o método de subsequência () executar no tempo de execução, no caso de "teste" == "teste" .substring (1), a piscina vai criar dois objeto string, "teste" e "! test", para que eles sejam diferentes objetos de referência, de modo que este caso vai retornar falso, no caso de "teste" == "teste" .substring (1) .intern (), o método de estagiário () irá colocar o ""! test ".substring (1)" para o conjunto de strings literais, portanto, neste caso, eles são mesmos objetos de referência, então retornará verdadeiro.

http://en.wikipedia.org/wiki/String_interning

string Internar é um método de armazenar apenas uma cópia de cada valor da cadeia distinta, que deve ser imutável. Internar cordas faz algumas tarefas de processamento de corda mais tempo ou espaço-eficiente com o custo de exigir mais tempo quando a corda é criado ou internado. Os valores distintos são armazenados em um conjunto de cadeia estagiário.

internado Cordas evitar a duplicação de Strings. Internar salva RAM à custa de mais tempo de CPU para detectar e substituir cordas duplicados. Há apenas uma cópia de cada String que foi internado, não importa como muitas referências apontar para ele. Desde Strings são imutáveis, se dois métodos diferentes aliás usar o mesmo String, eles podem compartilhar uma cópia da mesma cadeia. O processo de conversão de Cordas duplicados para aqueles compartilhados é chamado interning.String.intern () lhe dá o endereço do seqüência mestre canónico. Você pode comparar strings com == simples (o que compara ponteiros) internado em vez de é igual a que compara os caracteres da cadeia, um por um. Porque Strings são imutáveis, o processo interno é livre para economizar ainda mais espaço, por exemplo, por não criar um literal string separada para "pot" quando ele existe como um substring de algum outro literal como "hipopótamo".

Para ver mais http://mindprod.com/jgloss/interned.html

String s1 = "Anish";
        String s2 = "Anish";

        String s3 = new String("Anish");

        /*
         * When the intern method is invoked, if the pool already contains a
         * string equal to this String object as determined by the
         * method, then the string from the pool is
         * returned. Otherwise, this String object is added to the
         * pool and a reference to this String object is returned.
         */
        String s4 = new String("Anish").intern();
        if (s1 == s2) {
            System.out.println("s1 and s2 are same");
        }

        if (s1 == s3) {
            System.out.println("s1 and s3 are same");
        }

        if (s1 == s4) {
            System.out.println("s1 and s4 are same");
        }

OUTPUT

s1 and s2 are same
s1 and s4 are same
String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();

if (p1 == p2)
    System.out.println("p1 and p2 are the same");
if (p1 == p3)
    System.out.println("p1 and p3 are the same");
if (p1 == p4)
    System.out.println("p1 and p4 are the same");
if (p1 == p5)
    System.out.println("p1 and p5 are the same");
if (p1 == p6)
    System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
    System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
    System.out.println("p1 and p7 are the same");

Quando duas cadeias são criados de forma independente, intern() permite compará-los e também ajuda você a criar uma referência no conjunto de cadeia se a referência não existia antes.

Quando você usa String s = new String(hi), java cria uma nova instância da cadeia, mas quando você usa String s = "hi", cheques java se houver uma instância de palavra "oi" no código ou não e se ele existir, ele só retorna a referência .

Desde comparando strings é baseado em referência, intern() ajuda a você criar uma referência e permite comparar o conteúdo das strings.

Quando você usa intern() no código, ele limpa do espaço utilizado pela cadeia referindo ao mesmo objeto e apenas retorna a referência do mesmo objeto já existente na memória.

Mas no caso de p5 quando você estiver usando:

String p5 = new String(p3);

Somente conteúdo de p3 são copiados e p5 é criada recentemente. Portanto, não é internados .

Assim, a saída será:

p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    String s1 = "test";
    String s2 = new String("test");
    System.out.println(s1==s2);              //false
    System.out.println(s1==s2.intern());    //true --> because this time compiler is checking from string constant pool.
}

método corda estagiário () é usado para criar uma cópia exata do objeto string pilha no conjunto de cadeia constante. Os objetos string na piscina string constante são automaticamente internado, mas objetos string em pilha não são. O principal uso de criação de estagiários é salvar o espaço de memória e para realizar a comparação mais rápida de objetos string.

Fonte: O que é estagiário corda em java

Como você disse, esse método corda intern() vai encontrar primeiro da piscina String, se encontra, então ele irá retornar o objeto que aponta para isso, ou vai acrescentar uma nova seqüência na piscina.

    String s1 = "Hello";
    String s2 = "Hello";
    String s3 = "Hello".intern();
    String s4 = new String("Hello");

    System.out.println(s1 == s2);//true
    System.out.println(s1 == s3);//true
    System.out.println(s1 == s4.intern());//true

O s1 e s2 são dois objetos que apontam para a piscina String "Olá", e usando "Hello".intern() vai achar que s1 e s2. Então "s1 == s3" retorna verdadeiro, bem como ao s3.intern().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top