255 votes

Dois-je instancier les variables d'instance sur la déclaration ou dans le constructeur?

Est-il un avantage pour l'un et l'autre?

Exemple 1:

class A {
    B b = new B();
}

Exemple 2:

class A {
    B b;

    A() {
         b = new B();
    }
}

293voto

Bozho Points 273663
  • il n'y a pas de différence - l'instance de l'initialisation d'une variable est effectivement mis dans le constructeur(s) par le compilateur
  • la première variante est plus lisible
  • vous ne pouvez pas avoir de la manipulation d'exception avec la première variante
  • il est en outre l'initialisation du bloc, qui est ainsi mis dans le constructeur(s) par le compilateur:

    {
        a = new A();
    }
    

Vérification du Soleil, des explications et des conseils

À partir de ce tutoriel:

Champ déclarations, toutefois, ne font pas partie de la méthode, de sorte qu'ils ne peuvent pas être exécutés comme des états. Au lieu de cela, le compilateur Java génère une instance champ code d'initialisation automatique et le met dans le constructeur ou les constructeurs de la classe. Le code d'initialisation est inséré dans un constructeur dans l'ordre qu'il apparaît dans le code source, ce qui signifie qu'un champ d'initialiseur pouvez utiliser les valeurs initiales des champs déclarée avant.

En outre, vous pouvez paresseusement initialiser votre domaine. Dans les cas lors de l'initialisation d'un champ est une opération coûteuse, vous pouvez initialiser dès que c'est nécessaire:

ExpensiveObject o;

public ExpensiveObject getExpensiveObject() {
    if (o == null) {
        o = new ExpensiveObject();
    }
    return o;
}

Et en fin de compte (comme l'a souligné le projet de Loi), pour l'amour de la gestion de la dépendance, il est préférable d' éviter l' utilisation de l' new de l'opérateur de n'importe où dans votre classe. Au lieu de cela, à l'aide de l'Injection de Dépendance est préférable à - dire en laissant quelqu'un d'autre (une autre classe/cadre) instancier et injecter les dépendances dans votre classe.

39voto

Bill the Lizard Points 147311

Je n'hésiterais pas à utiliser l'une de ces méthodes, bien que votre exemple 2 est légèrement plus préférable. Au lieu de cela je voudrais utiliser:

class A{
   B b;

   A(B b) {
      this.b = b;
   }
}

Cela supprime la responsabilité de la création de l'objet B à partir du constructeur de A. Cela permet de rendre votre code plus testable et plus facile à maintenir dans le long terme. C'est un exemple très simple de l'Injection de Dépendance. L'idée est de réduire le couplage entre les deux classes A et B. Un avantage que cela vous donne, c'est que vous pouvez maintenant passer à tout objet qui s'étend B à Un constructeur de la et il va fonctionner.

15voto

TofuBeer Points 32441

mon "règle" (pratiquement jamais cassé) est de:

  • déclarer toutes les variables au début de un bloc
  • faire toutes les variables finale à moins qu'ils ne peut pas être
  • déclarer une variable par ligne
  • ne jamais initialiser une variable où déclaré
  • seulement initialiser quelque chose dans un constructeur quand il a besoin de données à partir de le constructeur à faire initialisation

Je voudrais donc avoir un code comme:

public class X
{
    public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
    private static final int A;
    private final int b;
    private int c;

    static 
    { 
        A = 42; 
    }

    {
        b = 7;
    }

    public X(final int val)
    {
        c = val;
    }

    public void foo(final boolean f)
    {
        final int d;
        int       e;

        d = 7;

        // I will eat my own eyes before using ?: - personal taste.
        if(f)
        {
            e = 1;
        }
        else
        {
            e = 2;
        }
    }
}

De cette façon, je suis toujours à 100% certain de l'endroit où chercher pour les déclarations de variables (au début d'un bloc), et de leurs affectations (dès qu'il fait sens, après la déclaration). Les vents de cette place sont susceptibles d'être plus efficace, car vous n'avez jamais initialiser une variable avec une valeur qui n'est pas utilisé (par exemple déclarer et init vars, puis lancer une exception avant la moitié de ces revendeurs à valeur ajoutée nécessaires pour avoir une valeur). Vous pouvez aussi ne pas le vent jusqu'fait inutile d'initialisation (par exemple int i = 0; et puis, plus tard, avant de "je" est utilisé, do i = 5;.

J'valeur consistance très bien, donc suite à cette "règle" est quelque chose que je fais tout le temps, et il les rend beaucoup plus facile de travailler avec le code puisque vous n'avez pas à chasser autour pour trouver des choses.

Votre kilométrage peut varier.

7voto

BalusC Points 498232

Exemple 2 est moins souple. Si vous ajoutez un autre constructeur, vous devez vous rappeler pour instancier le domaine que de constructeur. Il vous suffit d'instancier directement le champ, ou d'introduire de chargement paresseux quelque part dans un getter.

Si l'instanciation exige plus qu'une simple new, utilisez un initialiseur bloc. Cela va être exécuté indépendamment du constructeur utilisé. E. g.

public class A {
    private Properties properties;

    {
        try {
            properties = new Properties();
            properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties"));
        } catch (IOException e) {
            throw new ConfigurationException("Failed to load properties file.", e); // It's a subclass of RuntimeException.
        }
    }

    // ...

}

3voto

Vinko Vrsalovic Points 116138

Je prends c'est presque une question de goût, tant que l'initialisation est simple et n'a pas besoin de toute logique.

Le constructeur approche est un peu plus fragile si vous n'utilisez pas un initialiseur bloc, parce que si vous plus tard sur ajouter un deuxième constructeur et d'oublier d'initialiser b, vous obtiendrez un null b uniquement lors de l'utilisation de ce dernier constructeur.

Voir http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html pour plus de détails sur l'initialisation en Java (et pour les explications sur initalizer les blocs et les autres ne sont pas bien connus de l'initialisation).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X