Initialiser le champ avant le super constructeur d'exécution?
En Java, est-il possible d'initialiser un champ avant le super constructeur fonctionne?
Même le plus laid des hacks je peux venir avec sont rejetés par le compilateur:
class Base
{
Base(String someParameter)
{
System.out.println(this);
}
}
class Derived extends Base
{
private final int a;
Derived(String someParameter)
{
super(hack(someParameter, a = getValueFromDataBase()));
}
private static String hack(String returnValue, int ignored)
{
return returnValue;
}
public String toString()
{
return "a has value " + a;
}
}
Remarque: Le problème a disparu quand je suis passé de l'héritage de la délégation, mais je voudrais quand même savoir.
- êtes-vous essayer de pré-initialiser le champ
a
? - Je ne pense pas que vous pouvez le faire. Tout d'initialisation que vous faites dans une classe (même si c'est en dehors du constructeur) est déplacé à chaque constructeur après la
super
appel. Ainsi, le super constructeur est toujours exécuté avant que le champ de l'initialisation. - depuis
a
n'est accessible que dansDerived
, pourquoi est-il important qu'il obtient initialisé avantsuper()
est appelé? Initialisation après ne pas faire une différence dans l'exemple de votre fournir (sauf si vous appelez une méthode surchargée à partir du constructeur de Base, qui commence à avoir une odeur assez louche). - Efficace Java Article 17: "les Constructeurs ne doivent pas invoquer des méthodes substituables, directement ou indirectement, ( ... ) Si la méthode de remplacement dépend de l'initialisation effectuée par le constructeur de sous-classe, la méthode ne fonctionnera pas comme prévu."
- peut une dernière variable sera initialisée dans le constructeur?
- Ouais, bien sûr. Recherchez Immuable classes.
- Din sais pas qui! Merci.
- Laide Hack: Créer la classe Dérivée directement dans le bytecode java comme dans cette réponse: stackoverflow.com/questions/3278865/...
- En fait, cela fait une différence dans mon exemple, car
System.out.println(this)
appelle en internetoString()
, qui est surchargé d'imprimer la valeur dea
. - Oui, c'était mon point de vue - c'est la seule situation où il fait la différence et qui vous voudrez probablement à éviter.
- Je pense que ce qu'on a une meilleure solution qui peut être aussi bien utilisé pour ceci: stackoverflow.com/questions/2303604/..., Peut-être au lieu d'un hack() fonction que vous aurez besoin de faire un Hack de la classe, et vous pouvez vraiment utiliser la solution dans le lien
Vous devez vous connecter pour publier un commentaire.
Non, il n'y a aucun moyen de le faire.
Selon la langue specs, les variables d'instance ne sont pas encore initialisé jusqu'à un
super()
appel a été fait.Ce sont ces étapes effectuées lors du constructeur de l'étape de création de l'instance de la classe, prises à partir du lien:
Super constructeur de courir dans tous les cas, mais puisque nous parlons de la "laids " hacks", nous pouvons profiter de cette
Je n'ai jamais suggérons d'utiliser ce genre de hacks.
J'ai une façon de le faire.
Comme d'autres l'ont dit, vous ne pouvez pas initialiser le champ d'instance avant d'appeler le constructeur de la superclasse.
Mais il existe des solutions de contournement. L'une est de créer une usine de classe qui obtient la valeur et le transmet à la Dérivée du constructeur de la classe.
C'est interdit par la Java langage de spécification (section 8.8.7):
Le corps du constructeur devrait ressembler à ceci: