Je vois les POJO les plus immuables écrits comme ceci:
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;
}
}
Pourtant, j'ai tendance à les écrire comme ceci:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
Notez que les références sont finales, donc l'objet est toujours immuable. Cela me permet d’écrire moins de code et autorise un accès plus court (par 5 caractères: le get
et ()
).
Le seul inconvénient que je peux voir, c'est que si vous voulez modifier la mise en œuvre de getFoo()
la suite pour faire quelque chose de fou, vous ne pouvez pas. Mais de manière réaliste, cela ne se produit jamais car l'objet est immuable; vous pouvez vérifier pendant l'instanciation, créer des copies défensives immuables pendant l'instanciation (voir Guava, ImmutableList
par exemple) et préparer les objets foo
ou bar
pour l' get
appel.
Y a-t-il des inconvénients qui me manquent?
MODIFIER
Je suppose qu’un autre inconvénient qui me manque est la sérialisation des bibliothèques utilisant la réflexion par rapport aux méthodes commençant par get
ou is
, mais c’est une pratique plutôt terrible ...
la source
final
ne fait pas une variable l'objet immuable. J'utilise normalement une conception dans laquelle je définis desfinal
champs avant de créer un rappel afin que ce dernier puisse accéder à ces champs. Bien sûr, il peut appeler toutes les méthodes, y compris toutes lessetX
méthodes.String
,int
ouMyObject
. Dans la première version, ilfinal
s'agit uniquement de s'assurer que des méthodes autres que le constructeur de la classe n'essayent pasbar = 7;
, par exemple. Dans la deuxième version,final
est nécessaire pour empêcher les consommateurs de faire:MyObject x = new MyObject("hi", 5); x.bar = 7;
.Object
reste immuable. » Est trompeur - de cette façon , il semble que vous pensez que toutfinal Object
est immuable, qu'il n'est pas. Désolé pour le malentendu.myObj.getFoo().setFrob(...)
.Réponses:
Quatre inconvénients auxquels je peux penser:
Cela dit, votre version est nettement plus concise. S'il s'agit d'une classe spécialisée utilisée uniquement dans un package spécifique (la portée du package est peut-être une bonne idée ici), je peux envisager cette possibilité pour des éléments uniques. Mais je n'exposerais pas les principales API comme celle-ci.
la source
Débarrassez-vous des getters / setters aussi, et tout va bien!
C'est un sujet très controversé parmi les programmeurs Java.
Quoi qu'il en soit, il y a deux situations où j'utilise des variables publiques à la place (!) Des getters / setters:
la source
En termes simples:
la source
Un inconvénient possible que je peux constater immédiatement est que vous êtes lié à la représentation interne des données dans la classe. Ce n'est probablement pas une grosse affaire, mais si vous utilisez les setters et que vous décidez que foo et bar seront retournés par une autre classe définie ailleurs, les classes consommant MyObject ne seront pas obligées de changer. Il vous suffira de toucher MyObject. Cependant, si vous utilisez les valeurs nues, vous devrez toucher partout où votre MyObject est utilisé.
la source