54 votes

Pourquoi ne pas Java ont intializer listes comme en C++?

En C++, vous pouvez utiliser une liste d'initialiseur pour initialiser les champs de la classe avant que le constructeur ne commence à courir. Par exemple:

Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) {
    // Empty; already handled!
}

Je suis curieux de savoir pourquoi Java ne dispose pas d'une fonctionnalité similaire. Selon Core Java: Volume 1:

C++ utilise cette syntaxe spéciale pour appeler le champ des constructeurs. En Java, il n'est pas nécessaire, parce que les objets ont pas de sous-objets, seulement des pointeurs vers d'autres objets.

Voici mes questions:

  1. Que veulent-ils dire par "parce que les objets ont pas de sous-objets?" Je ne comprends pas ce qu'est un sous-objet est (j'ai essayé de regarder vers le haut); signifient-ils une instanciation d'une sous-classe qui étend la classe mère?

  2. Quant à savoir pourquoi Java n'a pas d'initialiseur de listes comme C++, je suppose que la raison en est que tous les champs sont déjà initialisés par défaut en Java, et aussi parce que Java utilise l' super mot-clé pour appeler le super(ou la base en C++ lingo) le constructeur de la classe. Est-ce correct?

100voto

templatetypedef Points 129554

En C++, initialiseur de listes sont nécessaires en raison de quelques fonctionnalités de langage qui soit ne sont pas présents dans l'utilisation de Java ou de travailler différemment en Java:

  1. const: En C++, vous pouvez définir les champs qui sont marqués const qui ne peuvent pas être affecté et doit être initialisé dans la liste d'initialiseur. Java n'ont final champs, mais vous pouvez lui attribuer final champs dans le corps d'un constructeur. En C++, de l'affectation à un const champ dans le constructeur est illégal.

  2. Références: En C++, les références (par opposition à des pointeurs) doit être initialisé à se lier à un objet. Il est illégal de créer une référence sans un initialiseur. En C++, le chemin que vous indiquez, c'est avec l'initialiseur de liste, car si vous étiez à se référer à la référence dans le corps du constructeur sans d'abord l'initialiser, vous seriez à l'aide d'un non initialisé de référence. En Java, les références aux objets se comportent comme C++ les pointeurs et peut être attribué à après créées. Ils ont juste valeur par défaut de null sinon.

  3. Direct des sous-objets. En C++, un objet peut contenir des objets directement en tant que champs, alors que dans des objets Java ne peut contenir des références à ces objets. C'est, en C++, si vous déclarez un objet qui a un string en tant que membre, l'espace de stockage pour que la chaîne est directement intégré à l'espace de l'objet lui-même, alors qu'en Java que vous venez de trouver de la place pour une référence à certains autres String objet stocké ailleurs. Par conséquent, C++ doit fournir un moyen pour vous de donner à ces sous-objets de valeurs d'origine, car sinon on venait de séjour non initialisée. Par défaut, il utilise le constructeur par défaut pour ces types, mais si vous souhaitez utiliser un autre constructeur ou pas de constructeur par défaut est disponible la liste d'initialiseur vous donne un moyen de contourner cela. En Java, vous n'avez pas besoin de vous inquiéter à ce sujet parce que les références par défaut est null, et vous pouvez ensuite attribuer à eux pour désigner les objets que vous voulez vraiment se référer. Si vous souhaitez utiliser un non-constructeur par défaut, alors vous n'avez pas besoin d'aucune syntaxe spéciale pour elle; il suffit de régler la référence à un objet initialisé par le constructeur.

Dans les rares cas où Java pourrait vouloir initialiseur de listes (par exemple, à l'appel de la superclasse des constructeurs ou de donner des valeurs par défaut pour ses champs), c'est géré par le biais de deux autres fonctionnalités de langage: l' super mot-clé à invoquer la superclasse des constructeurs, et le fait que les objets Java peuvent donner à leurs champs de valeurs par défaut au moment où elles sont déclarées. C++ ne prend pas en charge ces derniers (mais en C++0x ils changent ce; voir Bjarne la description du changement), et il ne peut pas soutenir les anciens à cause de l'héritage multiple, vous pouvez avoir besoin d'initialiser plusieurs objets de base et le terme super ne serait pas sans ambiguïté se référer à une seule classe de base.

Espérons que cette aide!

9voto

George Points 942

C++

Il y a une différence entre

ClassType t(initialization arguments);

et

ClassType * pt;

Ce dernier n'a pas besoin d'être initialisé (NULL). Le premier n'. Pensez-y comme un entier. Vous ne pouvez pas avoir un int sans valeur, MAIS vous pouvez avoir un int pointeur sans valeur.

Ainsi, lorsque vous avez:

class ClassType
{
    OtherClass value;
    OtherClass * reference;
};

Puis la déclaration:

ClassType object;

crée automatiquement une instance de OtherClass en value. Par conséquent, si OtherClass a l'initialisation, il doit être fait dans l' ClassType constructeur. Toutefois, reference est un pointeur (l'adresse en mémoire) et peut rester non initialisée. Si vous voulez un exemple d' OtherClass vous devez utiliser

object.reference = new OtherClass(initialization arguments);

Java

Il y a seulement

class ClassType
{
    OtherClass reference;
}

C'est l'équivalent d'un pointeur en C++. Dans ce cas, lorsque vous faites:

ClassType object = new ClassType();

Vous n'avez pas automatiquement créer une instance d' OtherClass. Par conséquent, vous n'avez pas à initialiser quoi que ce soit dans le constructeur, à moins que vous le souhaitez. Lorsque vous souhaitez qu'un objet d' OtherClass vous pouvez utiliser

object.reference = new OtherClass();

1voto

Mike Samuel Points 54712

Parce que Java n'a pas besoin d'eux afin de permettre l'initialisation des champs dont le type n'a pas de valeur nulle.

En C++

class C {
  D d;
}

sans un initialiseur de membre pour l' d, D::D() sera appelé, ce qui rend impossible d'initialiser le champ si il n'y a pas de zéro-type D. Cela peut se produire lors de l' D::D() est déclarée explicitement private.

En Java, il est connu de la valeur zéro pour tous les types référence, null, de sorte qu'un champ peut toujours être initialisé.

Java a également fait un gros travail pour veiller à ce que* tous final champs sont initialisés avant la première utilisation et avant que le constructeur se termine, alors que Java a une exigence comme C++ const champ d'initialisation de l'obligation, c'est juste surcharges this.fieldName = <expression> dans le corps du constructeur de champ moyen de l'initialisation.

  • : modulo les exceptions levées dans le ctor, remplacé les appels de méthode à partir de la classe de base, etc.

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