Um objeto String pode ser alterado?

no livro do Deitel é dito que quando se cria um objeto string seu conteúdo não pode ser mais alterado. Se for para ser alterado eu deveria usar a classe StringBuffer.

mas eu compilei e executei o seguinte código e não ocorreu problema algum:

public class testeString {
    public static void main(String[] args) {

        String str = new String();
        str = "primeiro";
        str = "segundo";

        System.out.println(str);

    }
}

e mesmo no livro ele sempre altera Strings com algum comando do tipo
str += num + “\n”;

Então fiquei confuso. alguém pode esclarecer?

Wdr, realmente o objeto String quando atribuido um valor não pode ser mais alterado.

O que acontece no seu código, que quando você atribui novo valor a referência do tipo String, o java cria um novo objeto na memoria do tipo String.

Ou seja no código que você postou abaixo

String str = new String(); str = "primeiro"; str = "segundo";

Quando terminar de executar o seu código, seu programa Java vai ter dois objetos no spool de String. Um onde aponta para o objeto string com o valor de “segundo” e o primeiro objeto com o valor de “primeiro” não é mais referenciado por ninguem, sendo qualificavel para a limpeza (garbage collect)

Acredito que no proprio livro do Deitel o mesmo explica com mais detalhes.

´
Qualquer dúvida, estamos ae…

puxa, fiquei mais confuso ainda…

por que o compilador não dá simplesmente uma mensagem de erro quando eu tento uma nova atribuição? Qual o sentido dele criar um novo objeto se em princípio uma String não pode ser alterada? De qualquer modo, pelo menos no fluxo lógico do programa, ela foi alterada, a questão é como o Java fez nos bastidores. É uma pegadinha para programadores novatos?

Então se eu usar um loop for com uma declaração str += valor; eu estarei criando um aterro sanitário para o coletor?

É um erro de sintaxe eu tentar atribuir um novo valor a uma String, apesar do compilador não acusar erro?

o próprio Deitel usou o loop com String que falei para arranjar texto em forma de tabela. (não sei se apenas para fins didáticos).

Wanderson.

se eu fizer

Respondendo suas perguntas…

Como o próprio deitel diz no livro, os objetos String são imutáveis, porém umas referência String pode mudar o objeto para qual está apontando quantas vezes quiser. No caso o que acontece com objetos Strings é que você não consegue modificá-los através de seus métodos. Você vai entender se executar o código a seguir:

...
String str = "teste";
str.concat("123");

System.out.println(str);
...

Como essas Strings são imutáveis, para se criar uma outra String “teste123” a JVM precisa criar um novo Objeto String, e adicioná-lo ao pool como disse Astork. Mas fique tranquilo! a JVM é inteligente, e se você quiser criar uma String que já exista ele não criará um novo objeto, apenas referenciará o já existente no pool :smiley:

Se você executar o código a seguir vai entender o que acontece, na verdade o método concat retorna uma String, que é a que acabou de ser criada pela JVM e tem o valor teste123.

A JVM é bem espertinha :smiley:
Ela não passa o garbage collectot no pool de Strings, então pode ficar tranquilo que suas Strings estarão seguras!

Não é um erro e é muito comum.

O que é importante você entender é que o objeto é diferente da referência, o que está na variável é a referência, não o objeto em si, ao atribuir algo em uma variável o que está sendo alterado é a referencia, o objeto permanece intacto. Tente entender essa diferença de objeto e referência porque é muito importante.

Exactamente, a questão fundamental aqui é realmente que o programador consiga diferenciar objectos de referências. As referências servem como indicadores aos objectos(e arrays). Pode haver mais do que uma referência para um dado objecto, mas nunca o contrário.

Isto não acontece só com Strings, mas com todo o tipo de objecto,corrijam-me se estiver errado.