Comment créer une variable qui ne peut être définie qu'une fois, mais n'est pas définitive en Java

Je veux une classe qui me permet d'en créer des instances de avec une variable de la fonction unset (le id), puis initialiser cette variable plus tard, et il immuable après l'initialisation. Effectivement, je voudrais un final variable que je peux l'initialiser à l'extérieur du constructeur.

Actuellement, je suis en improvisant avec un setter qui déclenche une Exception comme suit:

public class Example {

    private long id = 0;

    //Constructors and other variables and methods deleted for clarity

    public long getId() {
        return id;
    }

    public void setId(long id) throws Exception {
        if ( this.id == 0 ) {
            this.id = id;
        } else {
            throw new Exception("Can't change id once set");
        }
    }
}

Est-ce une bonne façon d'aller sur ce que je suis en train de faire? Je me sens comme je devrais être capable de mettre quelque chose comme immuable une fois initialisé, ou qu'il y est un modèle que je peux utiliser pour le rendre plus élégant.

  • Est-il une BONNE raison pour ne pas le mettre dans le constructeur?
  • que faire si l'OP doit avoir un constructeur par défaut ainsi?
  • Est-ce quelque chose qui pourrait se produire et doit être traité au cours de l'exécution du programme ou voulez-vous empêcher le programmeur de la mise plus d'une fois?
  • ce n'est pas le programmeur vous avez besoin de s'inquiéter.
  • puis je pense que ça devrait être ok pour être null (et pas en dernier) - une variable qui peut être définie qu'une fois se sent comme une pure violation du "principe de moindre surprise"
  • J'ai demandé parce que si ce cas ne devrait jamais se produire, j'utiliserais une affirmation plutôt qu'une exception.
  • et si le contrat de la classe stipule que tous les champs sont initialisés à des valeurs non nulles qu'est-ce que la suggestion? Je comprends que c'est un cas extrême, mais le contrat doit être respecté.
  • comment pourrait-il jamais être évité 🙂 si les champs doivent être non null, comment est définie une fois que la variable de la solution?
  • vous n'null case en regard de la valeur. Faire du design par contrat, bien que fastidieux, est d'une grande utilité dans ces scénarios. Si vous assurer que tous les mutateurs avoir à passer par une vérification sur l'objet que vous pouvez vérifier que votre objet a été mis à jour correctement.
  • Mais ils ne sont pas encore initialisé à la non null.
  • Quel est le problème avec cette façon de faire? Je l'aurais fait de la même façon: un setter qui lève une exception si vous essayez de régler une deuxième fois.
  • Je suis d'accord même si je pense toujours que c'est un mauvais "modèle".
  • Je ne peux pas mettre dans le constructeur, car je ne connais pas l'id de l'époque. L'ID est retourné à partir d'un serveur distant à une date ultérieure. Après l'écriture de cette question, j'ai décidé de re-conception de mes interactions afin que le serveur crée l'objet lui-même, mais je suis toujours intéressé à la meilleure approche ici.
  • Je pense que l'utilisation d'affirmer, c'est plus élégant que ce que j'ai fait ci-dessus, mais ça ne signifie pas que l'exception ne sera pas explicitement être jeté, donc je vais probablement oublier de le rattraper.
  • Quelle est la portée? Avez-vous besoin d'exposer la méthode de définition d'une manière ou d'un être isolé dans la même classe/méthode? Si son petit périmètre (classe, méthode, usine, package), vous pourriez être en mesure d'avoir une interface sans le setter qui vous exposer à l'extérieur et à créer de la mise en œuvre effective à l'intérieur de votre "champ d'application"....
  • J'aime l'idée de l'interface, très soigné. Pense à ce sujet.
  • cambecc dit ci-dessous "les Assertions sont désactivés par défaut--ils sont activés uniquement avec l'option-ea drapeau sur la JVM de la ligne de commande. Si le comportement de vos changements de classe en fonction de cet indicateur. Sans assertions activé (encore une fois, c'est la valeur par défaut), vous pouvez définir l'id autant de fois que vous le souhaitez." Peut-être les assertions ne sont pas si bonnes...