Pergunta

Esta poderia ser a pergunta mais idiota já pediu, mas eu acho que é bastante confuso para um novato Java.

  1. Alguém pode esclarecer o que se entende por imutável ?
  2. Por que é uma imutável String?
  3. Quais são as vantagens / desvantagens dos objetos imutáveis?
  4. Por que um objeto mutável, como StringBuilder ser preferido ao longo de Cordas e vice-versa?

Um exemplo agradável (em Java) será muito apreciado.

Foi útil?

Solução

meios imutáveis ??que uma vez que o construtor para um objeto foi concluída a execução dessa instância não pode ser alterado.

Isso é útil porque significa que você pode passar referências para o objeto ao redor, sem se preocupar que alguém vai mudar o seu conteúdo. Especialmente quando se lida com a concorrência, não há problemas de bloqueio com objetos que nunca mudam

por exemplo.

class Foo
{
     private final String myvar;

     public Foo(final String initialValue)
     {
         this.myvar = initialValue;
     }

     public String getValue()
     {
         return this.myvar;
     }
}

Foo não precisa se preocupar que o chamador para getValue() pode mudar o texto na cadeia.

Se você imaginar uma classe semelhante ao Foo, mas com um StringBuilder em vez de um String como um membro, você pode ver que um chamador getValue() seria capaz de alterar o atributo StringBuilder de uma instância Foo.

Também cuidado com os diferentes tipos de imutabilidade que você pode encontrar: Eric Lippert escreveu um artigo de blog sobre isso. Basicamente, você pode ter objetos cuja interface é imutável, mas nos bastidores mutables reais estado privado (e, portanto, não podem ser compartilhados com segurança entre threads).

Outras dicas

Um objecto imutável é um objecto onde os campos internos (ou, pelo menos, todos os campos internos que afectam o seu comportamento externo) não pode ser alterado.

Há uma série de vantagens para cordas imutáveis:

Performance: Tome a seguinte operação:

String substring = fullstring.substring(x,y);

A C subjacente para o método substring () é provavelmente algo como isto:

// Assume string is stored like this:
struct String { char* characters; unsigned int length; };

// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
    struct String* out = malloc(sizeof(struct String));
    out->characters = in->characters + begin;
    out->length = end - begin;
    return out;
}

Note que nenhum dos personagens têm de ser copiado! Se o objeto String foram mutável (os personagens poderiam mudar mais tarde), então você teria que copiar todos os caracteres, caso contrário, muda para caracteres na substring seria refletida na outra corda mais tarde.

Concorrência: Se a estrutura interna de um objeto imutável é válido, ele será sempre válido. Não há nenhuma chance de que diferentes segmentos podem criar um estado inválido dentro desse objeto. Assim, objetos imutáveis ??são thread-safe .

Coleta de lixo:. É muito mais fácil para o coletor de lixo para tomar decisões lógicas sobre objetos imutáveis ??

No entanto, também há desvantagens para imutabilidade:

Performance: Espere, eu pensei que você disse que o desempenho foi um upside de imutabilidade! Bem, é, às vezes, mas não sempre. Tome o seguinte código:

foo = foo.substring(0,4) + "a" + foo.substring(5);  // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder

As duas linhas de ambas substituir o quarto caractere com a letra "a". Não é só a segunda parte do código mais legível, é mais rápido. Olha como você teria que fazer o código subjacente para foo. Os substrings são fáceis, mas agora, porque já existe um carácter de espaço de cinco e outra coisa pode ser referência foo, você não pode simplesmente mudá-lo; você tem que copiar a seqüência inteira (é claro que alguma desta funcionalidade é captada em funções no real C subjacente, mas o ponto aqui é mostrar o código que é executado em um só lugar).

struct String* concatenate(struct String* first, struct String* second)
{
    struct String* new = malloc(sizeof(struct String));
    new->length = first->length + second->length;

    new->characters = malloc(new->length);

    int i;

    for(i = 0; i < first->length; i++)
        new->characters[i] = first->characters[i];

    for(; i - first->length < second->length; i++)
        new->characters[i] = second->characters[i - first->length];

    return new;
}

// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));

Note que concatenate é chamado duas vezes o que significa que toda a cadeia tem de ser loop através! Compare isso com o código C para a operação bar:

bar->characters[4] = 'a';

A operação corda mutável é, obviamente, muito mais rápido.

Em Conclusão: Na maioria dos casos, você quer uma seqüência imutável. Mas se você precisa fazer um monte de anexação e inserção em uma string, você precisa a mutabilidade de velocidade. Se você quiser os benefícios de segurança de simultaneidade e de coleta de lixo com ele é a chave para manter seus objetos mutáveis ??local para um método:

// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
    StringBuilder mutable;
    boolean first = true;

    for(int i = 0; i < strings.length; i++)
    {
        if(!first) first = false;
        else mutable.append(separator);

        mutable.append(strings[i]);
    }

    return mutable.toString();
}

Uma vez que o objeto mutable é uma referência local, você não precisa se preocupar com a segurança de simultaneidade (apenas um segmento cada vez toca). E uma vez que não é referenciado em qualquer outro lugar, só é alocada na pilha, por isso é desalocada assim que a chamada de função for concluído (você não precisa se preocupar com coleta de lixo). E você recebe todos os benefícios de ambos mutabilidade e imutabilidade de desempenho.

Na verdade Cordas não é imutável, se você usar a definição wikipedia sugerido acima.

estado de Cordas faz alterações pós-construção. Dê uma olhada no método hashCode (). Cordas armazena em cache o valor hashcode em um campo local, mas não calculá-lo até que a primeira chamada de hashCode (). Esta avaliação preguiçosa de hashcode coloca Cordas em uma posição interessante como um objeto imutável cujas mudanças de estado, mas não pode ser observada ter mudado sem o uso de reflexão.

Então, talvez a definição de imutável deve ser um objeto que não pode ser observada ter mudado.

Se as mudanças de estado em um objeto imutável após ele ter sido criado, mas ninguém pode vê-lo (sem reflexão) é o objeto ainda imutável?

Objetos imutáveis ??são objetos que não podem ser alterados por meio de programação. Eles são especialmente bons para ambientes multi-threaded ou outros ambientes onde mais de um processo é capaz de alterar (mutate) os valores em um objeto.

Só para esclarecer, no entanto, StringBuilder é realmente um objeto mutável, não um imutável. A java regulares String é imutável (o que significa que uma vez que foi criado você não pode alterar a seqüência subjacente sem alterar o objeto).

Por exemplo, digamos que eu tenho uma classe chamada ColoredString que tem um valor de cadeia e uma String cor:

public class ColoredString {

    private String color;
    private String string;

    public ColoredString(String color, String string) {
        this.color  = color;
        this.string = string;
    }

    public String getColor()  { return this.color;  }
    public String getString() { return this.string; }

    public void setColor(String newColor) {
        this.color = newColor;
    }

}

Neste exemplo, o ColoredString é dito ser mutável, porque você pode mudar (mutação) uma de suas principais propriedades sem criar uma nova classe ColoredString. A razão para isso pode ser ruim é, por exemplo, digamos que você tem uma aplicação gráfica que tem vários segmentos e você estiver usando ColoredStrings para imprimir dados para a janela. Se você tiver uma instância de ColoredString que foi criado como

new ColoredString("Blue", "This is a blue string!");

Em seguida, você esperaria a corda para estar sempre "Blue". Se outro segmento, no entanto, arrumou uma cópia desta instância e chamou

blueString.setColor("Red");

Você de repente, e, provavelmente, de forma inesperada, têm agora uma string "Red" quando você queria um "Blue". Devido a isso, objetos imutáveis ??são quase sempre preferível quando passando instâncias de objetos ao redor. Quando você tem um caso em que objetos mutáveis ??são realmente necessários, então você normalmente guardam o objet de apenas passando cópias fora de seu campo específico de controle.

Para recapitular, em Java, java.lang.String é um objeto imutável (que não pode ser alterado uma vez que é criado) e java.lang.StringBuilder é um objeto mutável, porque ele pode ser alterado sem a criação de uma nova instância.

  1. Em grandes aplicações sua posição comum para strings literais para ocupar grandes pedaços de memória. Então, para lidar eficientemente com a memória, a JVM aloca uma área chamada "constante piscina String". ( Note que na memória mesmo uma corda unreferenced leva em torno de um char [], um int para a sua extensão, e outro para o seu hashCode. para um número, pelo contrário, é necessário um máximo de oito bytes imediatos )
  2. Quando complier vem através de uma String literal ele verifica a piscina para ver se há uma literal idêntica já presente. E se um for encontrado, a referência ao novo literal é direcionado para a cadeia existente, e nenhuma nova 'String objeto literal' é criado (a cadeia existente simplesmente obtém uma referência adicional).
  3. Assim: Cordas mutabilidade economiza memória ...
  4. Mas quando qualquer do valor mudança variáveis, na verdade - é apenas a sua referência que mudou, não o valor na memória (portanto, não afetará as outras variáveis ??referência a ela) como visto abaixo ....

string s1 = "string Velho";

//s1 variable, refers to string in memory
        reference                 |     MEMORY       |
        variables                 |                  |

           [s1]   --------------->|   "Old String"   |

string s2 = s1;

//s2 refers to same string as s1
                                  |                  |
           [s1]   --------------->|   "Old String"   |
           [s2]   ------------------------^

s1 = "New String";

//s1 deletes reference to old string and points to the newly created one
           [s1]   -----|--------->|   "New String"   |
                       |          |                  |
                       |~~~~~~~~~X|   "Old String"   |
           [s2]   ------------------------^

A string original 'na memória' não muda, mas a variável de referência foi alterado de modo a que ela se refere à nova cadeia. E se não tivéssemos s2, "String Velho" ainda estaria na memória, mas nós não vai ser capaz de acessá-lo ...

meios "imutáveis" você não pode mudar o valor. Se você tiver uma instância da classe String, qualquer método que você chama o que parece modificar o valor, vai realmente criar uma outra cadeia.

String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"

Para preservar as alterações que você deve fazer algo parecido com isto foo = foo.sustring (3);

Imutável vs mutável pode ser engraçado quando você trabalha com coleções. Pense sobre o que vai acontecer se você usar objeto mutável como uma chave para o mapa e, em seguida, alterar o valor. (Dica: pense sobre equals e hashCode)

java.time

Pode ser um pouco tarde, mas, a fim de entender o que um objeto imutável é, considere o seguinte exemplo do novo Java 8 Data e API Time ( java.time ). Como você provavelmente sabe todos os objetos de data de Java 8 são imutável para que no exemplo a seguir

LocalDate date = LocalDate.of(2014, 3, 18); 
date.plusYears(2);
System.out.println(date);

Output:

2014/03/18

Isto imprime o mesmo ano como a data inicial porque o plusYears(2) retorna um novo objeto para a data antiga ainda permanece inalterado porque é um objeto imutável. Uma vez criada, você não pode modificá-lo ainda mais ea variável data ainda pontos para ele.

Então, que exemplo de código deve capturar e utilizar o novo objeto instanciado e retornado por essa chamada para plusYears.

LocalDate date = LocalDate.of(2014, 3, 18); 
LocalDate dateAfterTwoYears = date.plusYears(2);

Date.toString () ... 2014/03/18

dateAfterTwoYears.toString () ... 2016/03/18

Eu realmente gosto da explicação de SCJP Sun Certified Programmer for Java 5 Guia de Estudo .

Para fazer Java memória mais eficiente, a JVM deixa de lado uma área especial de memória chamado de "String constante piscina." Quando o compilador encontra um literal String, ele verifica a piscina para ver se uma seqüência idêntica já existe. Se for encontrada uma correspondência, a referência ao novo literal é direcionado para a cadeia existente, e nenhum novo objeto String literal é criado.

Objetos que são imutáveis ??não pode ter seu estado alterado depois de terem sido criadas.

Existem três principais razões para usar objetos imutáveis, sempre que possível, todas as quais irão ajudar a reduzir o número de erros que você introduzir em seu código:

  • É muito mais fácil raciocinar sobre como o programa funciona quando você sabe que o estado de um objeto não pode ser alterado por outro método
  • Objetos imutáveis ??são automaticamente thread-safe (assumindo que eles são publicados com segurança) para que nunca mais será a causa daqueles difícil de pin-down multithreading erros
  • Imutável objetos sempre terão o mesmo código hash, para que possam ser utilizadas como as teclas em um HashMap (ou similar). Se o código hash de um elemento em uma tabela hash foi a mudança, a entrada da tabela, então, efetivamente ser perdidos, uma vez que as tentativas de encontrá-lo na tabela acabaria procurando no lugar errado. Esta é a principal razão que os objetos String são imutáveis ??-. Eles são freqüentemente usados ??como chaves HashMap

Existem também algumas outras otimizações que você pode ser capaz de fazer no código quando você sabe que o estado de um objeto é imutável - cache o hash calculado, por exemplo - mas estes são otimizações e, portanto, não quase tão interessante

Um significado tem a ver com a forma como o valor é armazenado no computador, por uma corda .Net por exemplo, isso significa que a string na memória não pode ser alterado, quando você pensa que está mudando isso, você está no fato a criação de uma nova seqüência na memória e apontar a variável existente (que é apenas um ponteiro para a coleção real de caracteres em outro lugar) para a nova cadeia.

String s1="Hi";
String s2=s1;
s1="Bye";

System.out.println(s2); //Hi  (if String was mutable output would be: Bye)
System.out.println(s1); //Bye

s1="Hi":. Um s1 objeto foi criado com o valor "Hi" nele

s2=s1:. Um s2 objeto é criado com referência ao objeto s1

s1="Bye": o valor do objeto s1 anterior não muda porque s1 tem tipo String eo tipo String é um tipo imutável, em vez do compilador criar um novo objeto String com o valor "Bye" e s1 referência a ele. aqui quando imprimir valor s2, o resultado será "Hi" e não "Bye", porque s2 referenciado anterior objeto s1 que tinha valor "Hi".

meios imutáveis ??que uma vez que o objeto é criado, não de seus membros vai mudar. String é imutável desde que você não pode mudar seu conteúdo. Por exemplo:

String s1 = "  abc  ";
String s2 = s1.trim();

No código acima, a string s1 não mudou, outro objeto (s2) foi criado usando s1.

Imutável simplesmente significar imutável ou não modificável. Uma vez objeto string é criado seus dados ou o estado não pode ser alterado

Veja o exemplo abaixo,

class Testimmutablestring{  
  public static void main(String args[]){  
    String s="Future";  
    s.concat(" World");//concat() method appends the string at the end  
    System.out.println(s);//will print Future because strings are immutable objects  
  }  
 }  

Vamos começar a idéia considerando diagrama abaixo,

enter descrição da imagem aqui

Neste diagrama, você pode ver novo objeto criado como "World Future". Mas não alterar .Because String is immutable "Future". s, ainda se referem a "Future". Se você precisa chamar "Future World",

String s="Future";  
s=s.concat(" World");  
System.out.println(s);//print Future World

Por que corda objetos imutáveis ??em Java?

Como o Java usa o conceito de literal string. Suponhamos que existem 5 variáveis ??de referência, refere-se a todo um objecto "futuro" .Se uma variável de referência muda o valor do objecto, que vai ser afectado de todas as variáveis ??de referência. É por isso que os objetos String são imutáveis ??em Java.

Uma vez instanciado, não pode ser alterada. Considere uma classe que uma instância pode ser usada como a chave para um hashtable ou similar. Confira Java melhores práticas.

Imutável Objetos

Um objeto é considerado imutável se seu estado não pode mudar depois que ele é construído. confiança máxima em objetos imutáveis ??é amplamente aceito como uma boa estratégia para a criação de simples, código confiável.

Objetos imutáveis ??são particularmente úteis em aplicações simultâneas. Uma vez que eles não podem mudar de estado, eles não podem ser corrompido por interferência fio ou observado em um estado inconsistente.

Os programadores são muitas vezes relutantes em empregar objetos imutáveis, porque se preocupam com o custo de criar um novo objeto ao invés de atualizar um objeto no local. O impacto da criação do objeto é muitas vezes superestimada, e pode ser compensado por algumas das eficiências associadas com objetos imutáveis. Estes incluem a diminuição da sobrecarga devido à coleta de lixo, ea eliminação de código necessário para proteger objetos mutáveis ??da corrupção.

As seguintes subseções tomar uma classe cujas instâncias são mutáveis ??e deriva uma classe com instâncias imutáveis ??a partir dele. Ao fazê-lo, eles dão as regras gerais para este tipo de conversão e demonstrar algumas das vantagens de objetos imutáveis.

Fonte

docs oráculo diz

Um objeto é considerado imutável se o seu estado não pode mudar depois que ele É construído. confiança máxima em objetos imutáveis ??é amplamente aceito como uma boa estratégia para a criação de simples, código confiável.

Objetos imutáveis ??são particularmente úteis em aplicações simultâneas. Uma vez que eles não podem mudar de estado, eles não podem ser corrompido por fio interferência ou observado num estado incoerente.

Eu gosto desta frase da pós

Imutável objetos programação facilidade de simultaneidade

Um objeto imutável é o que você não pode modificar depois de criá-lo. Um exemplo típico são strings literais.

A D linguagem de programação, que se torna cada vez mais popular, tem uma noção de "imutabilidade" através de palavras-chave "invariável". Verifique artigo deste Dr.Dobb sobre isso - http: // dobbscodetalk .com / index.php? option = com_myblog & show = Invariant-Strings.html & Itemid = 29 . Ele explica o problema perfeitamente.

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