Strings Java: "String s = new String ("silly");"

Sou um tipo de C++ a aprender Java. Estou a ler um Java eficaz e algo me confundiu. Diz para nunca escrever um código como este:
String s = new String("silly");

porque cria objectos desnecessários String. Mas em vez disso deve ser escrito assim:

String s = "No longer silly";
Está bem, até agora...No entanto, dada esta classe:

public final class CaseInsensitiveString {
    private String s;
    public CaseInsensitiveString(String s) {
        if (s == null) {
            throw new NullPointerException();
        }
        this.s = s;
    }
    :
    :
}

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
  1. Porque é que a primeira declaração está bem? Não devia ser?

    CaseInsensitiveString cis = "Polish";

  2. Como faço para que CaseInsensitiveString me comporte como String de modo que a declaração acima está OK (com e sem estender String)? O que é que tem o String que faz com que seja bom apenas ser capaz de passá-lo um literal como esse? Pelo que sei, não há nenhum conceito de" construtor de cópias " em Java?

 82
Author: vaxquis, 2008-12-02

23 answers

String é uma classe especial embutida da língua. É apenas para a classe String em que você deve evitar dizer

String s = new String("Polish");

Porque o literal "Polish" já é do tipo String, e estás a criar um objecto extra desnecessário. Para qualquer outra classe, dizendo:

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

É a coisa certa (e única, neste caso) a fazer.

 107
Author: Adam Rosenfield, 2008-12-02 16:21:18

Eu acredito que o principal benefício de usar a forma literal (ou seja, "foo" ao invés de Nova Cadeia ("foo")) é que todos os literais de cadeia são 'internados' pelo VM. Em outras palavras, ele é adicionado a um pool tal que qualquer outro código que cria a mesma string irá usar a String agregada ao invés de criar uma nova instância.

Para ilustrar, o seguinte código irá imprimir verdadeiro para a primeira linha, mas falso para a Segunda:

System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
 53
Author: Leigh, 2008-12-02 16:26:05

As cordas são tratadas um pouco especialmente em java, são imutáveis, por isso é seguro para elas serem tratadas pela contagem de referências.

Se escrever

String s = "Polish";
String t = "Polish";

Então s e t realmente se referem ao mesmo objeto, E s==t retornará verdadeiro, pois "==" para objetos lidos "é o mesmo objeto" (ou pode, de qualquer forma, eu"não tenho certeza se isso é parte da linguagem spec real ou simplesmente um detalhe da implementação do compilador-então talvez não seja seguro confiar nisso) .

Se escrever

String s = new String("Polish");
String t = new String("Polish");

Então s!=t(porque você criou explicitamente uma nova string) embora S. igual a (t) irá retornar true (porque string adiciona este comportamento a igual).

A coisa que queres escrever,

CaseInsensitiveString cis = "Polish";

Não pode funcionar porque você está pensando que as citações são algum tipo de construtor de curto-circuito para o seu objeto, quando na verdade isso só funciona para java Velho e simples.idioma.Cadeia.

 30
Author: Steve B., 2008-12-02 16:36:23
String s1="foo";

O Literal vai para a piscina e o s1 vai referir-se.

String s2="foo";

Desta vez ele vai verificar "Foo" literal já está disponível em StringPool ou não como agora ele existe então s2 vai se referir ao mesmo literal.

String s3=new String("foo");

" Foo "literal será criado em StringPool primeiro, em seguida, através de string ARG constructor String objeto será criado I. e" foo " no heap devido à criação de objeto através de novo operador, em seguida, s3 irá encaminhá-lo.

String s4=new String("foo");

O mesmo que s3

Então ... System.out.println(s1==s2);// **true** due to literal comparison.

E System.out.println(s3==s4);// **false** due to object

A comparação (s3 e s4 são criados em diferentes locais de heap)

 19
Author: Vikas, 2016-02-07 09:40:53

Strings são especiais em Java - são imutáveis, e constantes de string são automaticamente transformadas em objetos String.

Não há maneira do teu exemplo se aplicar a qualquer outra classe.

Nem se pode estender {[[[0]}, porque é declarado como final, o que significa que não é permitida nenhuma sub-classe.

 12
Author: Alnitak, 2008-12-02 16:25:36
As cordas Java são interessantes. Parece que as respostas cobriram alguns dos pontos interessantes. Aqui estão os meus dois cêntimos.

As cordas são imutáveis (você nunca pode mudá-las)

String x = "x";
x = "Y"; 
  • a primeira linha irá criar uma variável x que irá conter o valor de texto "x". O JVM vai olhar em seu conjunto de valores de cadeia e ver se " x " existe, se ele existe, ele vai apontar a variável x para ele, se ele não existe, ele vai criá-lo e, em seguida, fazer o atribuição
  • a segunda linha irá remover a referência a "x" e ver se "Y" existe no conjunto de valores de cadeia. Se ele existe, ele vai atribuí-lo, se não, ele vai criá-lo primeiro, em seguida, atribuição. Como os valores de string são usados ou não, o espaço de memória no conjunto de valores de string será recuperado.

Comparações de cadeias de caracteres dependem do que está a comparar

String a1 = new String("A");

String a2 = new String("A");
  • a1 não é igual a a2
  • a1 e a2 são referências de objectos
  • Quando a cadeia é explicitamente declarada, novas instâncias são criadas e as suas referências não serão as mesmas.
Acho que estás no caminho errado ao tentar usar a classe caseinsensível. Deixa as cordas em paz. O que você realmente se importa é como você exibir ou comparar os valores. Use outra classe para formatar a string ou para fazer comparações.

I. e.

TextUtility.compare(string 1, string 2) 
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)
Já que estás a fazer a aula, podes fazer as comparações. o que você quer - compare os valores do texto.
 7
Author: mson, 2012-04-12 13:13:01

Você não Pode. as coisas entre aspas em Java são especialmente reconhecidas pelo compilador como Strings, e infelizmente você não pode sobrepor isso (ou extender {[[0]} - é declarado final).

 6
Author: Dan Vinton, 2008-12-02 16:20:00

A melhor maneira de responder à tua pergunta seria familiarizar-te com a "String constant pool". Em java, objetos string são imutáveis (que eu.e seus valores não podem ser alterados, uma vez que eles são inicializados), então, quando a edição de um objeto de cadeia de caracteres que você acabar criando uma nova editado objeto de cadeia de caracteres wherease o objeto antigo simplesmente flutua em torno de uma memória especial ares chamada "constante de seqüência de caracteres de piscina". criar um novo objecto de texto por

String s = "Hello";

Só irá criar um objecto de cadeia de caracteres na piscina e na as referências s referir-se-ão a ele, mas usando

String s = new String("Hello");

Você cria dois objetos de cadeia: um na piscina e o outro na pilha. a referência se referirá ao objeto no heap.

 6
Author: WickeD, 2012-05-19 04:30:33

- Como faço para que o Caseinsensibilitivestring se comporte como String para que a declaração acima esteja ok (com e w/out string estendendo)? O que é que tem o String que faz com que seja bom apenas ser capaz de passá-lo um literal como esse? Pelo que sei, não há nenhum conceito de" construtor de cópias " em Java, certo?

Já foi dito o suficiente desde o primeiro ponto. "Polonês" é um texto literal e não pode ser atribuído à classe Caseinsentivivivivestring. Agora sobre o ... segundo ponto

Embora você não possa criar novos literais, você pode seguir o primeiro item desse livro para uma abordagem "semelhante", de modo que as seguintes afirmações são verdadeiras:

    // Lets test the insensitiveness
    CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
    CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

    assert cis5 == cis6;
    assert cis5.equals(cis6);
Aqui está o código.
C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;

public final class CaseInsensitiveString  {


    private static final Map<String,CaseInsensitiveString> innerPool 
                                = new HashMap<String,CaseInsensitiveString>();

    private final String s;


    // Effective Java Item 1: Consider providing static factory methods instead of constructors
    public static CaseInsensitiveString valueOf( String s ) {

        if ( s == null ) {
            return null;
        }
        String value = s.toLowerCase();

        if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
             CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
         }

         return CaseInsensitiveString.innerPool.get( value );   
    }

    // Class constructor: This creates a new instance each time it is invoked.
    public CaseInsensitiveString(String s){
        if (s == null) {
            throw new NullPointerException();
         }         
         this.s = s.toLowerCase();
    }

    public boolean equals( Object other ) {
         if ( other instanceof CaseInsensitiveString ) {
              CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
             return this.s.equals( otherInstance.s );
         }

         return false;
    }


    public int hashCode(){
         return this.s.hashCode();
    }

/ / testar a classe usando a palavra-chave "Asser"

    public static void main( String [] args ) {

        // Creating two different objects as in new String("Polish") == new String("Polish") is false
        CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
        CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");

        // references cis1 and cis2 points to differents objects.
        // so the following is true
        assert cis1 !=  cis2;      // Yes they're different
        assert cis1.equals(cis2);  // Yes they're equals thanks to the equals method

        // Now let's try the valueOf idiom
        CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
        CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");

        // References cis3 and cis4 points to same  object.
        // so the following is true
        assert cis3 == cis4;      // Yes they point to the same object
        assert cis3.equals(cis4); // and still equals.

        // Lets test the insensitiveness
        CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
        CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

        assert cis5 == cis6;
        assert cis5.equals(cis6);

        // Futhermore
        CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
        CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");

        assert cis8 == cis5 && cis7 == cis6;
        assert cis7.equals(cis5) && cis6.equals(cis8);
    }

}

C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java


C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString

C:\oreyes\samples\java\insensitive>
Isto é, criar um conjunto interno de objectos de Resistência Caseinsensibilizante, e devolver a instância correntemente de lá.

Desta forma, o " = " operador devolve verdadeiro para dois objectos referências que representam o mesmo valor .

Isto é útil quando objectos semelhantes são usados com muita frequência e a criação de custos é dispendiosa.

A documentação da classe de texto indica que a classe usa um conjunto interno

A classe não está completa, algumas questões interessantes surgem quando tentamos caminhar o conteúdo do objeto na implementação da interface CharSequence, mas este código é bom o suficiente para mostrar como esse item no livro poderia ser aplicado.

É importante notar que ao usar o objeto internalPool, as referências não são liberadas e, portanto, não são coletáveis lixo, e isso pode se tornar um problema se um monte de objetos são criados.

Ele funciona para a classe de cadeia porque é usado intensivamente e o conjunto é constituído apenas de objeto "internado".

Ele funciona bem para a classe booleana também, porque há apenas dois valores possíveis.

E finalmente essa é também a razão pela qual valor de (int) in class Integer is limited to -128 to 127 int values.
 4
Author: OscarRyz, 2009-07-14 20:57:11

Em seu primeiro exemplo, você está criando uma String, "silly" e, em seguida, passando-a como um parâmetro para o construtor de cópia de outra String, que faz uma segunda String que é idêntica à primeira. Uma vez que as Strings Java são imutáveis (algo que frequentemente fere pessoas que são usadas para strings C), Este é um desperdício desnecessário de recursos. Em vez disso, você deve usar o segundo exemplo, porque ele salta vários passos desnecessários.

No entanto, o texto literal não é um Caseinsensibilitivestring assim lá você não pode fazer o que você quer em seu último exemplo. Além disso, não há nenhuma maneira de sobrecarregar um operador de fundição como você pode em C++ para que não haja literalmente nenhuma maneira de fazer o que você quer. Em vez disso, você deve passá-lo como um parâmetro para o construtor da sua classe. Claro, provavelmente usaria fio.para usar a língua e acabar com isto.

Além disso, o seu tratamento Caseinsensibilizante deve implementar a interface de CharSequence, bem como, provavelmente, a serializável e Interfaces comparáveis. Claro, se você implementar comparável, você deve sobrepor igual() e hashCode() também.
 3
Author: James, 2008-12-02 16:29:11
 3
Author: javaguy, 2010-05-04 21:08:53

CaseInsensitiveString não é um String embora contenha um String. A String literalmente, por exemplo, "exemplo" só pode ser atribuído a String.

 3
Author: fastcodejava, 2010-12-14 03:54:52

Caseinsensibilitivestring E String são objectos diferentes. Não podes fazer isso.

CaseInsensitiveString cis = "Polish";

Porque "polaco" é uma cadeia, não um Caseinsensibilitivestring. Se a String estendesse a String CaseInsensitiveString então você estaria bem, mas obviamente não.

E não te preocupes com a construção aqui, não vais fazer objectos desnecessários. Se você olhar para o código do construtor, tudo o que ele está fazendo é armazenar uma referência à cadeia que você passou. Nada mais está a ser criado.

No caso String s = nova String ("foobar") está a fazer algo diferente. Você está primeiro criando a string literal "foobar", em seguida, criando uma cópia dela, construindo uma nova string a partir dela. Não há necessidade de criar essa cópia.

 2
Author: Herms, 2008-12-02 17:03:46
Quando dizem para escrever
String s = "Silly";

Em vez de

String s = new String("Silly");

Eles significam isso ao criar um objeto de cadeia de caracteres porque ambas as afirmações acima criam um objeto de cadeia de caracteres, mas a nova versão String () cria dois objetos de cadeia de caracteres: um em heap e o outro em string constant pool. Portanto, usando mais memória.

Mas quando escreves

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

Você não está criando uma String em vez disso você está criando um objeto de classe CaseInsensitiveString. Por isso você precisa usar o novo operador.

 2
Author: , 2012-05-19 04:27:39

Se eu entendi corretamente, sua pergunta significa por que não podemos criar um objeto atribuindo-lhe diretamente um valor, não vamos restringi-lo a uma embalagem da classe String em java.

Para responder que eu diria apenas, linguagens de programação puramente orientadas a objetos têm algumas construções e diz, que todos os literais quando escritos sozinhos podem ser diretamente transformados em um objeto do tipo dado.

Isso significa que, se o intérprete vir 3, será convertido em um objeto inteiro porque inteiro é o tipo definido para tais literais.

Se o interpretador vir alguma coisa entre aspas simples como' a ' irá criar directamente um objecto de carácter tipo, não precisa de O especificar, dado que a linguagem define o objecto por omissão de carácter tipo para ele.

Similarmente, se o interpretador vê algo em"", ele será considerado como um objeto de seu tipo padrão, ou seja, cadeia de caracteres. Isto é um código nativo a trabalhar ao fundo.

Graças a Curso de aula de vídeo do MIT às 6: 00, onde recebi a dica para esta resposta.
 1
Author: dharam, 2012-05-24 18:12:23

Em Java a sintaxe "texto" cria uma instância da classe java.idioma.Cadeia. A missão:

String foo = "text";

É uma tarefa simples, sem necessidade de construtor de cópias.

MyString bar = "text";
O que quer que faças, é ilegal, porque a classe MyString não é java.idioma.String ou uma superclasse de java.idioma.Cadeia.
 0
Author: Darron, 2008-12-02 16:22:56

Primeiro, você não pode fazer uma classe que se estende de String, porque String é uma classe final. E o java gerencia Cadeias de caracteres de forma diferente das outras classes, por isso só com String você pode fazer

String s = "Polish";
Mas, para a tua turma, tens de invocar o construtor. Então, esse código é bom.
 0
Author: Lucas Gabriel Sánchez, 2008-12-02 16:23:55

Eu acrescentaria que Java tem Copy constructors ...

É um construtor comum com um objecto do mesmo tipo que o argumento.
 0
Author: PhiLho, 2008-12-02 17:15:14

Na maioria das versões do JDK as duas versões serão as mesmas:

String s = new String ("silly");

String s = "no longer silly";

Porque as cadeias de caracteres são imutáveis, o compilador mantém uma lista de constantes de cadeias de caracteres e se tentar fazer uma nova irá primeiro verificar se a cadeia de caracteres já está definida. Se for então uma referência à cadeia imutável existente é retornada.

Para esclarecer-quando dizes "String s =" estás a definir uma nova variável que ocupa espaço na pilha - então se você diz "não mais bobo" ou nova String("bobo") exatamente a mesma coisa acontece - uma nova string constante é compilada em sua aplicação e os pontos de referência para isso.

Não vejo a distinção aqui. No entanto, para a sua própria classe, que não é imutável, este comportamento é irrelevante e você deve chamar o seu construtor.

Atualização: eu estava errado! Com base num voto negativo e num comentário anexado, testei este facto e apercebi-me de que a minha compreender é errado-nova String ("Silly") realmente cria uma nova string ao invés de reutilizar a existente. Não sei por que isso seria (Qual é o benefício?) mas o código fala mais alto que as palavras!

 0
Author: Ewan Makepeace, 2008-12-04 01:04:11

O texto é uma das classes especiais nas quais você pode criá-las sem a nova parte do anel

É o mesmo que

Int x = y;

Ou

Char c;

 0
Author: Tolga E, 2009-07-14 21:00:12

É uma lei básica que Strings em java são imutáveis e sensíveis a maiúsculas.

 0
Author: user1945649, 2013-01-06 18:48:43
 String str1 = "foo"; 
 String str2 = "foo"; 

Ambos str1 e str2 pertencem ao mesmo objeto de String, "foo", B'coz Java gerencia Strings em StringPool, então se uma nova variável se refere à mesma String, ela não cria outra, mas atribui a mesma alerady presente em StringPool.

 String str1 = new String("foo"); 
 String str2 = new String("foo");

Aqui tanto o str1 como o str2 pertencem a diferentes objectos, o b'coz new String() cria forçosamente um novo objecto de texto.

 0
Author: Akash5288, 2013-12-27 08:29:38

O Java cria um objecto de texto para cada texto literal que usa no seu código. Sempre que "" é usado, é o mesmo que chamar new String().

Cadeias de caracteres são dados complexos que apenas" agem " como dados primitivos. Literais de cordas são realmente objetos, mesmo que fingamos que eles são literais primitivos, como 6, 6.0, 'c', etc. Assim, o texto "literal" "text" devolve um novo objecto de texto com valor char[] value = {'t','e','x','t}. Portanto, chamando
new String("text"); 

É na verdade semelhante a chamar

new String(new String(new char[]{'t','e','x','t'}));
Com sorte, de aqui, você pode ver por que seu livro considera isso redundante.

Para referência, aqui está a implementação do texto: http://www.docjar.com/html/api/java/lang/String.java.html

É uma leitura divertida e pode inspirar algum discernimento. Também é ótimo para iniciantes para ler e tentar entender, como o código demonstra código muito profissional e compatível com a Convenção.

Outra boa referência é o tutorial Java sobre Strings: http://docs.oracle.com/javase/tutorial/java/data/strings.html

 -1
Author: Patrick Michaelsen, 2015-06-23 23:28:55