128 votes

Pourquoi certains prétendent-ils que Java ' mise en oeuvre des génériques est mauvais ?

J’ai parfois entendu qu’avec des médicaments génériques, Java n’a pas faire les choses. (référence le plus proche, ici)

Pardonnez mon inexpérience, mais ce qui aurait rendu leur mieux ?

159voto

Jon Skeet Points 692016

Mauvais:

  • Type d'information est perdue au moment de la compilation, au moment de l'exécution, vous ne pouvez pas dire de quel type il est "censé" être
  • Ne peut pas être utilisé pour les types de valeur (c'est un biggie .NET un List<byte> est vraiment soutenu par un byte[] par exemple, et pas de la boxe est requis)
  • La syntaxe pour appeler des méthodes génériques suce (OMI)
  • La syntaxe pour les contraintes peut prêter à confusion
  • Caractères de remplacement est généralement source de confusion
  • Diverses restrictions en raison de la coulée, etc

Bon:

  • Wildcarding permet de covariance/contravariance être spécifié lors de l'appel de côté, ce qui est très soigné dans de nombreuses situations
  • C'est mieux que rien!

26voto

Paul Tomblin Points 83687

Le plus gros problème est que Java génériques sont une seule chose de compilation, et vous pouvez le renverser en cours d’exécution. C# est félicité parce qu’il ne contrôle plus de moment de l’exécution. Il y a un échange de vues très bon dans ce post, et liens vers d’autres discussions.

20voto

JaredPar Points 333733

Le principal problème est que Java n'ont pas réellement de génériques au moment de l'exécution. C'est un moment de la compilation de la fonctionnalité.

Lorsque vous créez une classe générique en Java, ils utilisent une méthode appelée "Type d'Effacement de" supprimer tous les types génériques de la classe et de essentiellement les remplacer par Objet. La mile high version de génériques est que le compilateur insère simplement jette à la spécifié de type générique, chaque fois qu'il apparaît dans le corps de la méthode.

Cela a beaucoup d'inconvénients. L'un des plus grands, à mon humble avis, c'est que vous ne pouvez pas utiliser la réflexion pour contrôler un type générique. Les Types ne sont pas réellement des génériques dans le byte code et donc ne peut pas être inspecté génériques.

Excellente vue d'ensemble des différences ici: http://www.jprl.com/Blog/archive/development/2007/Aug-31.html

15voto

cletus Points 276888
  1. Exécution de la mise en œuvre (c'est à dire pas de type d'effacement);
  2. La capacité à utiliser les types primitifs (ceci est lié à (1));
  3. Tandis que les caractères de remplacement est utile à la syntaxe et à savoir quand l'utiliser, c'est quelque chose que les souches de beaucoup de gens. et
  4. Aucune amélioration des performances (en raison de (1); Java des génériques sucre syntaxique pour castingi Objets).

(1) conduit à des comportements très étranges. Le meilleur exemple que je peux penser à est de. Supposons:

public class MyClass<T> {
  T getStuff() { ... }
  List<String> getOtherStuff() { ... }
}

ensuite déclarer deux variables:

MyClass<T> m1 = ...
MyClass m2 = ...

Maintenant, appel getOtherStuff():

List<String> list1 = m1.getOtherStuff(); 
List<String> list2 = m2.getOtherStuff(); 

La seconde a son argument de type générique dépouillé par le compilateur car c'est une crue de type (le type paramétré n'est pas fourni), même si elle a rien à voir avec le type paramétré.

Je vais aussi mentionner mon préféré de la déclaration à partir du JDK:

public class Enum<T extends Enum<T>>

En dehors de caractères de remplacement (qui est un sac mixte), je pense juste que l' .Net les génériques sont mieux.

12voto

Clint Miller Points 6339

Je vais jeter vraiment un avis controversé. Les génériques compliquer la langue et de compliquer le code. Par exemple, disons que j'ai une carte que les cartes d'une chaîne à une liste de chaînes de caractères. Dans les vieux jours, je pourrais déclarer simplement comme

Map someMap;

Maintenant, je dois le déclarer comme

Map<String, List<String>> someMap;

Et chaque fois que je passe dans une certaine méthode, je dois répéter ce gros long déclaration une fois de plus. À mon avis, tout ce que la saisie de texte supplémentaire distrait le développeur et l'emmène hors de la "zone". Aussi, lorsque le code est rempli avec beaucoup de trucs, parfois, il est dur de revenir plus tard et rapidement passer au crible tous les trucs pour trouver l'important logique.

Java a déjà une mauvaise réputation d'être l'une des plus verbeux langues d'usage courant, et les génériques vient de s'ajouter à ce problème.

Et que croyez-vous vraiment acheter pour tout ce que supplémentaires de verbosité? Combien de fois avez-vous vraiment eu des problèmes là où quelqu'un a mis un Entier dans une collection qui est censé tenir les Cordes, ou lorsque quelqu'un a essayé de tirer une Chaîne de caractères à partir d'un ensemble d'Entiers? Dans mes 10 années d'expérience de travail au bâtiment commercial d'applications Java, cela n'a jamais été une grande source d'erreurs. Donc, je ne suis pas vraiment sûr de ce que vous obtenez pour le niveau de verbosité. - Il vraiment juste me frappe comme une surcharge bureaucratique bagages.

Maintenant, je vais vraiment faire de la controverse. Ce que je considère comme le plus grand problème avec les collections en Java 1.4 est la nécessité de transtypage de partout. J'ai vue ces typecasts supplémentaire, en clair trucs qui ont beaucoup des mêmes problèmes que les génériques. Ainsi, par exemple, je ne peux pas juste faire

List someList = someMap.get("some key");

J'ai à faire

List someList = (List) someMap.get("some key");

La raison, bien sûr, c'est que get() renvoie un Objet qui est un supertype de Liste. Si la cession ne peut pas être fait sans un transtypage. Encore une fois, pensez à la façon dont beaucoup que la règle vraiment acheter de vous. De mon expérience, pas beaucoup.

Je pense que Java aurait été mieux si 1) elle n'avait pas ajouté les génériques, mais 2) au lieu avait permis la conversion implicite d'un supertype à un sous-type. Laissez incorrect jette être pris au moment de l'exécution. Ensuite, j'aurais eu la simplicité de la définition de l'

Map someMap;

et, plus tard, de faire

List someList = someMap.get("some key");

tous les trucs serait allé, et je ne pense pas que je serais l'introduction d'une nouvelle grande source d'un bug dans mon code.

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