163 votes

Quelles sont les différences entre les types "génériques" en C++ et en Java ?

Java dispose de génériques et C++ fournit un modèle de programmation très solide avec template s. Alors, quelle est la différence entre les génériques C++ et Java ?

2 votes

160voto

Alexandru Nedelcu Points 3801

Il y a une grande différence entre eux. En C++, il n'est pas nécessaire de spécifier une classe ou une interface pour le type générique. C'est pourquoi vous pouvez créer des fonctions et des classes véritablement génériques, avec la réserve d'un typage plus lâche.

template <typename T> T sum(T a, T b) { return a + b; }

La méthode ci-dessus ajoute deux objets du même type, et peut être utilisée pour tout type T qui dispose de l'opérateur "+".

En Java, vous devez spécifier un type si vous voulez appeler des méthodes sur les objets passés, quelque chose comme :

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

En C++, les fonctions/classes génériques ne peuvent être définies que dans les en-têtes, car le compilateur génère différentes fonctions pour différents types (avec lesquels elles sont invoquées). La compilation est donc plus lente. En Java, la compilation ne présente pas de pénalité majeure, mais Java utilise une technique appelée "effacement" où le type générique est effacé à l'exécution, de sorte qu'à l'exécution, Java appelle en fait ...

Something sum(Something a, Something b) { return a.add ( b ); }

La programmation générique en Java n'est donc pas vraiment utile, il s'agit seulement d'un petit sucre syntaxique pour faciliter la nouvelle construction foreach.

EDITAR: l'opinion ci-dessus sur l'utilité a été écrite par une personne plus jeune. Les génériques de Java aident à la sécurité des types, bien sûr.

28 votes

Il a parfaitement raison de dire que ce n'est qu'un sucre syntaxique élaboré.

39 votes

Ce n'est pas un sucre purement syntaxique. Le compilateur utilise ces informations pour vérifier les types. Même si l'information n'est pas disponible à l'exécution, je n'appellerais pas quelque chose que le compilateur utilise simplement "sucre syntaxique". Si vous l'appelez ainsi, alors le C n'est que du sucre syntaxique pour l'assemblage, et c'est juste du sucre syntaxique pour le code machine :)

47 votes

Je pense sucre syntaxique est utile.

130voto

cletus Points 276888

Les génériques Java sont massivement différent des modèles C++.

En C++, les modèles sont essentiellement un ensemble glorifié de préprocesseurs/macro ( Note : puisque certaines personnes semblent incapables de comprendre une analogie, je ne dis pas que le traitement des modèles est une macro). En Java, il s'agit essentiellement d'un sucre syntaxique permettant de minimiser le casting d'objets. Voici un modèle assez décent introduction aux modèles C++ et aux génériques Java .

Pour approfondir ce point : lorsque vous utilisez un template C++, vous créez essentiellement une autre copie du code, tout comme si vous utilisiez un fichier de type #define macro. Cela vous permet de faire des choses comme int dans les définitions de modèles qui déterminent la taille des tableaux et autres.

Java ne fonctionne pas comme ça. En Java, tous les objets s'étendent de java.lang.Object donc, avant les génériques, on écrivait du code comme ça :

public class PhoneNumbers {
    private Map phoneNumbers = new HashMap();

    public String getPhoneNumber(String name) {
      return (String) phoneNumbers.get(name);
    }
}

parce que tous les types de collections Java utilisaient Object comme type de base, ce qui permettait d'y mettre n'importe quoi. Java 5 arrive et ajoute les génériques, ce qui permet de faire des choses comme.. :

public class PhoneNumbers {
    private Map<String, String> phoneNumbers = new HashMap<String, String>();

    public String getPhoneNumber(String name) {
        return phoneNumbers.get(name);
    }
}

Et c'est tout ce que sont les Java Generics : des enveloppes pour les objets de casting. C'est parce que les génériques Java ne sont pas raffinés. Ils utilisent l'effacement des types. Cette décision a été prise parce que les génériques Java sont arrivés si tard qu'ils ne voulaient pas rompre la compatibilité ascendante (une Map<String, String> est utilisable chaque fois qu'un Map est demandée). Comparez cela à .Net/C# où l'effacement des types n'est pas utilisé, ce qui entraîne toutes sortes de différences (par exemple, vous pouvez utiliser des types primitifs et des IEnumerable y IEnumerable<T> n'ont aucun rapport entre elles).

Et une classe utilisant des génériques compilée avec un compilateur Java 5+ est utilisable sur le JDK 1.4 (en supposant qu'elle n'utilise pas d'autres fonctionnalités ou classes qui nécessitent Java 5+).

C'est pourquoi les génériques Java sont appelés sucre syntaxique .

Mais cette décision sur la façon de faire des génériques a des effets profonds, à tel point que le (superbe) FAQ sur les génériques Java a vu le jour pour répondre aux très nombreuses questions que les gens se posent sur les génériques Java.

Les modèles C++ possèdent un certain nombre de caractéristiques que les génériques Java n'ont pas :

  • Utilisation d'arguments de type primitif.

    Par exemple :

    template<class T, int i>
    class Matrix {
        int T[i][i];
        ...
    }

    Java ne permet pas l'utilisation d'arguments de type primitif dans les génériques.

  • Utilisation de arguments de type par défaut C'est une fonctionnalité qui me manque en Java, mais il y a des raisons de compatibilité ascendante pour cela ;

  • Java permet de délimiter les arguments.

    Par exemple :

    public class ObservableList<T extends List> {
        ...
    }

Il faut vraiment souligner que les invocations de modèles avec des arguments différents sont vraiment des types différents. Elles ne partagent même pas de membres statiques. En Java, ce n'est pas le cas.

Mis à part les différences avec les génériques, pour être complet, voici un exemple de comparaison de base entre C++ et Java (et un autre ).

Et je peux aussi suggérer Penser en Java . En tant que programmeur C++, une grande partie des concepts tels que les objets seront déjà une seconde nature, mais il existe des différences subtiles. Il peut donc être utile d'avoir un texte d'introduction, même si vous ne faites que survoler certaines parties.

Une grande partie de ce que vous apprendrez en apprenant Java est constituée de toutes les bibliothèques (à la fois standard - ce qui est fourni dans le JDK - et non standard, qui inclut des choses couramment utilisées comme Spring). La syntaxe Java est plus verbeuse que la syntaxe C++ et ne possède pas beaucoup de caractéristiques C++ (par exemple, la surcharge des opérateurs, l'héritage multiple, le mécanisme de destruction, etc.

0 votes

Ils sont complètement différents dans leur implémentation, mais équivalents (ou du moins similaires) dans leur concept, c'est ce que Tina a demandé.

1 votes

Ils ne sont pas équivalents en termes de concept. Le meilleur exemple est le modèle de modèle curieusement récurrent. Le deuxième meilleur exemple est la conception orientée politique. Le troisième meilleur exemple est le fait que le C++ permet de passer des nombres entiers entre crochets (myArray<5>).

1 votes

Non, ils ne sont pas équivalents dans le concept. Il y a un certain chevauchement dans le concept, mais pas beaucoup. Les deux permettent de créer des List<T>, mais cela ne va pas plus loin. Les templates C++ vont beaucoup plus loin.

92voto

Shog9 Points 82052

Le C++ a des modèles. Java a des génériques, qui ressemblent un peu aux modèles C++, mais ils sont très, très différents.

Les templates fonctionnent, comme leur nom l'indique, en fournissant au compilateur un (attendez...) template qu'il peut utiliser pour générer du code sécurisé en remplissant les paramètres du template.

Les génériques, tels que je les comprends, fonctionnent dans l'autre sens : les paramètres de type sont utilisés par le compilateur pour vérifier que le code qui les utilise est sûr du point de vue du type, mais le code résultant est généré sans aucun type.

Pensez aux modèles C++ comme un vraiment bien et les génériques Java en tant qu'outil de génération automatique de typecasts.

5 votes

C'est une explication assez bonne et concise. Une modification que je serais tenté d'apporter est que les génériques Java sont un outil pour générer automatiquement des typescasts. dont la sécurité est garantie (avec certaines conditions). D'une certaine manière, elles sont liées à la fonction const . Un objet en C++ ne sera pas modifié par un const à moins que le const - est rejetée. De même, les castings implicites créés par les types génériques en Java sont garantis comme étant "sûrs", à moins que les paramètres du type ne soient manuellement castés quelque part dans le code.

17voto

KeithB Points 9459

La spécialisation est une autre caractéristique des modèles C++ que les génériques Java ne possèdent pas. Cela vous permet d'avoir une implémentation différente pour des types spécifiques. Ainsi, vous pouvez, par exemple, avoir une version hautement optimisée pour un type int tout en disposant d'une version générique pour le reste des types. Ou vous pouvez avoir des versions différentes pour les types pointeurs et non-pointeurs. Cela s'avère pratique si vous voulez opérer sur l'objet déréférencé lorsqu'on vous donne un pointeur.

1 votes

+1 la spécialisation des modèles est incroyablement importante pour la métaprogrammation à la compilation - cette différence en elle-même rend les génériques java beaucoup moins puissants.

13voto

Julien Chastang Points 8357

Il existe une excellente explication de ce sujet dans Génériques et collections Java Par Maurice Naftalin, Philip Wadler. Je recommande vivement ce livre. Je cite :

Les génériques en Java ressemblent aux modèles en C++. ... La syntaxe est délibérément similaire et la sémantique est délibérément différente. ... Sémantiquement, les génériques Java sont définis par effacement, alors que les sont définis par l'expansion.

Veuillez lire l'explication complète aquí .

alt text
(source : <a href="http://oreilly.com/catalog/covers/0596527756_cat.gif" rel="nofollow noreferrer">oreilly.com </a>)

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