Question

Je lisais récemment un peu de Java et suis tombé sur quelque chose de nouveau (un idiome?): dans le programme, les classes comportant plusieurs constructeurs incluraient toujours un constructeur vide. Par exemple:

public class Genotype {
  private boolean bits[];
  private int rating;
  private int length;
  private Random random;

  public Genotype() {              //  <= THIS is the bandit, this one right here
    random = new Random();
  }

  /* creates a Random genetoype */
  public Genotype(int length, Random r) {
    random = r;
    this.length = length;
    bits = new boolean[length];

    for(int i=0;i<length;i++) {
        bits[i] =random.nextBoolean();
    }
  }

  /* copy constructor */
  public Genotype(Genotype g,Random r) {
    random = r;
    bits = new boolean[g.length];
    rating = g.rating;
    length = g.length;

    for(int i=0;i<length;i++) {
        bits[i] = g.bits[i];
    }

  }
}

Le premier constructeur ne semble pas être un "réel". constructeur, il semble que dans tous les cas l’un des autres constructeurs sera utilisé. Alors, pourquoi ce constructeur est-il défini?

Était-ce utile?

La solution

Je ne suis pas sûr que le code que vous étiez en train de lire était de haute qualité (j’ai déjà passé en revue des codes de bioinformatique qui ne sont malheureusement pas écrits par des développeurs professionnels). Par exemple, ce troisième constructeur n’est pas un constructeur de copie et, en général, ce code pose des problèmes; je ne lirais donc pas trop dedans ".

Le premier constructeur est un constructeur par défaut. Il n’initialise que le strict minimum et permet aux utilisateurs de régler le reste à l’aide de getters et de setters. D’autres constructeurs sont souvent des "constructeurs de commodité". qui aident à créer des objets avec moins d'appels. Cependant, cela peut souvent conduire à des incohérences entre les constructeurs. En fait, des recherches récentes montrent qu’un constructeur par défaut avec des appels ultérieurs aux setters est préférable.

Il existe également des cas où un constructeur par défaut est critique. Par exemple, certains frameworks tels que digester (utilisé pour créer des objets directement à partir de XML) utilisent des constructeurs par défaut. JavaBeans utilise généralement les constructeurs par défaut, etc.

De plus, certaines classes héritent d'autres classes. vous pouvez voir un constructeur par défaut lorsque l’initialisation de l’objet parent est "assez bonne".

Dans ce cas précis, si ce constructeur n'était pas défini, il faudrait connaître tous les détails à l'avance. Ce n’est pas toujours préférable.

Enfin, certains IDE génèrent automatiquement un constructeur par défaut, il est possible que celui qui a écrit la classe ait eu peur de l’éliminer.

Autres conseils

L'objet est-il Serializable ? ?

  

Pour permettre la sérialisation des sous-types de classes non sérialisables, le sous-type peut assumer la responsabilité de la sauvegarde et de la restauration de l'état des champs de package public, protégé et (s'il est accessible). Le sous-type peut assumer cette responsabilité uniquement si la classe qu'elle étend a un constructeur no-arg accessible pour initialiser l'état de la classe. C'est une erreur de déclarer une classe Serializable si ce n'est pas le cas. L'erreur sera détectée à l'exécution.

     

Lors de la désérialisation, les champs des classes non sérialisables seront initialisés à l'aide du constructeur public ou du constructeur no-arg protégé de la classe. Un constructeur no-arg doit être accessible à la sous-classe sérialisable. Les champs des sous-classes sérialisables seront restaurés à partir du flux

Oui, je suis d'accord avec le "blanc". constructeur ne doit pas toujours exister (selon mon expérience, les débutants commettent souvent cette erreur), bien qu’il existe des cas où un constructeur vierge suffirait. Toutefois, si le constructeur vierge enfreint l'invariant selon lequel tous les membres sont correctement instanciés après la construction , le constructeur vierge ne doit pas être utilisé. Si le constructeur est compliqué, il est préférable de diviser la construction en plusieurs méthodes protégées / privées. Utilisez ensuite une méthode static ou une autre classe Factory pour appeler les méthodes protégées pour la construction, si nécessaire.

Ce que j'ai écrit ci-dessus est le scénario idéal. Cependant, des frameworks tels que spring suppriment la logique du constructeur hors du code et dans certains fichiers de configuration XML. Vous pouvez avoir des fonctions getter et setter, mais vous pouvez probablement les éviter depuis l'interface, comme décrit ici .

Le constructeur par défaut n'est PAS obligatoire.

Si aucun constructeur n'est défini dans la classe, le constructeur par défaut (vide) sera créé automatiquement. Si vous avez fourni un ou plusieurs constructeurs paramétrés, le constructeur par défaut ne sera pas créé automatiquement et il est préférable de le créer vous-même. Les frameworks qui utilisent l'injection de dépendance et la création de proxy dynamique au moment de l'exécution nécessitent généralement un constructeur par défaut. Donc, cela dépend des cas d’utilisation de la classe que vous écrivez.

Le constructeur par défaut n’est pas une bonne pratique pour la vue fonctionnelle. Le constructeur par défaut est utilisé si l'objet a une visibilité globale sur une méthode: par exemple, vous souhaitez enregistrer l'état actuel d'un objet dans un champ try / catch. vous pouvez coder

MyObejct myObject=null
try{...
}catch(Exception e){
    log.error(myObject);//maybe print null. information?
}

ou préférez-vous

MyObejct myObject=new Object();
try{...
}catch(Exception e){
log.error(myObject);//sure print  myobject.toString, never null. More information
}

?

De plus, créer un objet VIDE n'a pas beaucoup de logique, mais instatier un objet NULL est nuisible à mon avis. Vous pouvez lire ce message

Ce n'est PAS un constructeur de copie. En gros, vous voulez des constructeurs vides lorsque vous travaillez avec un framework. Il doit toujours y avoir un constructeur vide, bien sûr, public ou privé, mais au moins, cela vous permet de garder le contrôle de la manière dont la classe est instanciée (ou non).

J'écris habituellement un constructeur qui initialise complètement l'objet; s’il y en a d’autres, ils appellent tous cela (...) avec les valeurs par défaut appropriées.

Un objet doit être initialisé à 100% et prêt à être utilisé à la création.

Certains frameworks, par exemple Hibernate, exigent un constructeur sans argument. Leur confrontation avec les meilleures pratiques me met parfois mal à l'aise.

Avoir un constructeur par défaut et vide (vide) vous empêche d’avoir des champs finaux. Cela conduit à beaucoup de mutabilité là où cela n’est souvent pas nécessaire.

Le modèle de générateur vous permet de mélanger ces deux styles et de permettre une initialisation plus souple tout en conservant son immuabilité en cachant un constructeur à plusieurs arguments derrière l’usine.

Pour certaines classes POJO ou classes simples, le constructeur par défaut est utile lorsque vous souhaitez parfois effectuer des tests unitaires sur la classe qui les utilise. Vous n'avez pas besoin de vous moquer d'eux, vous pouvez créer un objet avec le constructeur par défaut et tester l'ensemble de valeurs et obtenir d'eux ou les transmettre en tant qu'argument.

Vous voulez créer un constructeur vierge pour les classes qui ont étendu cette et depuis que la classe a été étendue ... l’enfant a maintenant super qui fait référence à la classe située au-dessus, c’est son parent. Dans le cas où l'enfant n'a pas spécifié super (matériel) ... le matériel à l'intérieur pour référencer les autres constructeurs à utiliser va maintenant tenter de référencer le constructeur vide.

Je ne sais pas quelle sera l'erreur. Je suis en train de coder ma première relation d'objet parent maintenant et je cherchais des choses ici ha des applaudissements.

Je suppose que je devrais ajouter le moment où vous créez un constructeur qui n'est pas le constructeur vide mais vous perdez le constructeur vide par défaut. Désormais, super (), qui est celui par défaut dans la classe étendue, n'aura pas quelque chose à viser. Bien sûr, si vous avez créé les classes étendues pour gérer super en spécifiant sur lequel se débarrasse de la valeur par défaut super (), vous éviterez ceci, mais que se passera-t-il si quelqu'un veut utiliser votre classe et l'étendre sans se rendre compte qu'il n'y en a pas? t un ensemble vide quand vous pourriez avoir vient d'en créer un.

Ceci est mon premier article mais je voulais comprendre comment je le comprends.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top