Eu vejo os POJOs mais imutáveis escritos assim:
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
No entanto, tenho a tendência de escrevê-los assim:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Observe que as referências são finais, portanto o objeto ainda é imutável. Deixa-me escrever menos código e permite mais curto (por 5 caracteres: o get
e ()
) acesso.
A única desvantagem que vejo é que, se você deseja alterar a implementação do getFoo()
caminho para fazer algo louco, não pode. Mas realisticamente, isso nunca acontece porque o Objeto é imutável; você pode verificar durante a instanciação, criar cópias defensivas imutáveis durante a instanciação (consulte Goiabas, ImmutableList
por exemplo) e preparar os objetos foo
ou bar
para a get
chamada.
Faltam algumas desvantagens?
EDITAR
Suponho que outra desvantagem que estou perdendo são as bibliotecas de serialização usando reflexão sobre os métodos que começam com get
or is
, mas essa é uma prática bastante terrível ...
fonte
final
não torna uma variável o objeto imutável. Eu normalmente uso um design em que definofinal
campos antes de criar retorno de chamada para que o retorno de chamada possa acessar esses campos. Obviamente, ele pode chamar todos os métodos, incluindo quaisquersetX
métodos.String
,int
ouMyObject
. Na primeira versão,final
é apenas para garantir que outros métodos além do construtor da classe não tentembar = 7;
, por exemplo. Na segunda versão,final
é necessário evitar que os consumidores a fazer:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
ainda é imutável " é enganoso - dessa maneira, parece que você acha que algumfinal Object
é imutável, o que não é. Desculpe pelo mal entendido.myObj.getFoo().setFrob(...)
.Respostas:
Quatro desvantagens que consigo pensar:
Dito isto, sua versão é definitivamente mais concisa. Se essa era uma classe especializada usada apenas dentro de um pacote específico (talvez o escopo do pacote seja uma boa idéia aqui), posso considerar isso para casos pontuais. Mas eu não exporia grandes APIs como esta.
fonte
Livre-se dos getters / setters também, e você está bem!
Este é um tópico altamente controverso entre os programadores Java.
De qualquer forma, existem duas situações em que eu uso variáveis públicas em vez (!) De getters / setters:
fonte
Nas palavras dos leigos:
fonte
Uma possível desvantagem que vejo de imediato é que você está vinculado à representação interna dos dados na classe. Isso provavelmente não é um grande negócio, mas se você usar os setters e decidir que foo e bar serão retornados de alguma outra classe definida em outro lugar, as classes que consomem MyObject não precisam mudar. Você só precisaria tocar em MyObject. No entanto, se você usar os valores nus, terá que tocar em todos os lugares que o MyObject eu usei.
fonte