Tout ce qui est proposé ici permettra toujours de code comme avant. On n'enlève rien. Les "anciennes" syntaxes seront toujours valides. On ne fait qu'en introduire de nouvelles.
Vincent
Ben si justement, c'est tout la le probleme, ca ne reste que du sucre syntaxique au final on a bien une map toute simple et le compilateur qui met des cast la ou il faut dans le bytecode (en gros la ou on les mettait manuellement en java 1.4-). Donc aucune difference avec la creation d'une Map<Object, Object>.
On peut deja faire sans aucun probleme :Citation:
Et ça ferait quoi ce code là ? :aie:
Code:
1
2 Map anagrams = (Map<String, List<String>>)new HashMap<>();
Il est possible de caster HashMap<Object, Object> en Map<String, List<String>> et de recaster cette derniere en Map<Object, Object> . On a juste le warning habituel :Code:Map anagrams = (Map<String, List<String>>)new HashMap();
Code:
1
2 Note: test\TestCast.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
Code:
1
2
3
4
5
6 test\TestCast.java:24: warning: [unchecked] unchecked cast found : java.util.HashMap required: java.util.Map<java.lang.String,java.util.List<java.lang.String>> Map anagrams = (Map<String, List<String>>)new HashMap(); ^ 1 warning
Merci pour ces précisions bouye ;)
Pour.
:arrow: Pas de perte d'informations, pas d'ambiguités, bref que des atouts ...
Pour, la plupart des raisons invoquées me semblant tout à fait valables. Regrettons quand même les <>, qui sont sans doute pas utiles (peut être pour la lecture, et encore).
CONTRE, parce que il est déjà possible, par l'inférence automatique, de supprimer complètement les répétitions.
Ainsi, pour créer un HashMap on peut écrire simplement :
Avec, comme méthode nouv :Code:
1
2
3
4HashMap<String, Integer> hash; hash = nouv();
On voit que je ne répète nulle part <String, Integer>.Code:
1
2
3
4
5 public static <A, B> HashMap<A, B> nouv() { return new HashMap<A, B>(); }
Pour exploiter cette propriété il suffirait de rajouter des méthodes de création d'bbjets génériques adéquates dans le JDK, ce qui serait nettement plus léger, et mieux, à mon avis, que de changer la syntaxe.
C'est ce que je fais déjà dans mon code, (ou à peu près), où, dans chaque classe générique que je fais, j'écris ma petite méthode statique nouv qui simplifie l'écriture.
Bah tu dois t'amuser si tu codes une classe utilitaire ayant des méthodes pour tous les cas de création de Map, Set, List, et autres types utilisant les génériques. Ça alourdi le code et niveau maintenabilité c'est pas le top non plus.
Bah non, son code est totalement adapté, pour n'importe quel typage de son HashMap il utilise la même fonction. Ya juste une fonction par type. Mais il ne fais plus 50 new, il n'en fait qu'un par fonction ;)
F.
Oui, heu... je suis pas Sun, moi, je vais pas m'amuser à faire une méthode pour chaque cas de création...
Au demeurant, il suffirait à Sun de les inclure dans chaque classe générique, ce qui me semble largement plus facile que de changer la syntaxe.
Certes, mais d'un autre coté tu utilises rarement toutes les collections existantes dans un programme, par contre tu en instancie souvent une poignée d'une même collection ;)
F.
J'ai voté contre.
1. Par principe, je suis pour la séparation du type de la variable et du type de l'instance. J'irai meme jusqu'a imposer que le type d'une variable soit toujours une interface. :aie:
2. Si le but c'est la lisibilité alors le gain est vraiment minime. Autant carrément supprimer le mot clé new et faire des allocations facon "C":
Code:
1
2 HashMap<String, List<String>> anagrams;
Pour moi, c'est exactement le contraire :)
Et donc je suis pour la simplification, mais contre la solution proposée. Je verrais plutôt d'un bon oeil un truc "à la" dotnet:
où toute la déclaration est après le = .Code:var mymap = new Map<Context,Layer>();
Celà, bien sûr, uniquement quand l'écriture à simplifier comprend un type déclaré et un type instancié identiques. Dans le cas contraire, il faut conserver l'écriture actuelle.
Thorna, je suis plutôt de l'avis d'adiGuba.
Aussi, je ne comprend pas pourquoi tu peux trouver le type de création plus important que le type déclaré ?
Aurais tu des arguments pour nous faire comprendre ton point de vue ? ;)
Perso cela ne m'enchante pas :?
:arrow: On perd toute l'abstraction des types...
:arrow: J'utilise une Map, et je me fiche de son implémentation exacte. Bref la déclaration comporte tout ce dont j'ai besoin de savoir. L'appel du constructeur se contente de créer une implémentation...Code:Map<Context,Layer> map = ...;
a++
Comme quelqu'un le dit un peu plus haut, à son avis, tous les types déclarés devraient être des interfaces.
Sans aller jusqu'à pousser le raisonnement aussi loin, ça veut quand même quelque part dire qu'on déclare par exemple un "fourre-tout" véhicule (une interface qui peut décrire aussi bien des camions que des voitures ou des vélos...) et qu'on instancie un Camion, ou un Vélo, ou une Voiture alors qu'il est interdit d'instancier un véhicule... Ce qui laisse trainer dans mon esprit l'idée que le "vrai" type est celui qu'on instancie. Bien sûr, la notion d'héritage est là pour qu'on puisse gérer partout où c'est nécessaire des véhicules, tout en sachant qu'en y regardant de plus près, il s'agit vraiment de Camion, de Vélo...
Je ne suis pas spécialiste de la théorie des langages, c'est juste un ressenti personnel, issu de 30 ans de programmation dans une bonne quinzaine de langages divers ( aahh le basic GFA, l'assembleur Z80; ... ;) ).
Dans ce cas, pourquoi ne pas écrireCitation:
On perd toute l'abstraction des types...
J'utilise une Map, et je me fiche de son implémentation exacte. Bref la déclaration comporte tout ce dont j'ai besoin de savoir. L'appel du constructeur se contente de créer une implémentation...Code:Map<Context,Layer> map = ...;
sans préciser new map(...) ?Code:Map<Context,Layer> map = new (paramètres)
Parce que pour la création on a besoin de connaitre le type précis pour pouvoir le créer : va-t-on instancier une HashMap, une TreeMap, ou une autre Map ???
Par contre quand on l'utilise dans 99% des cas on n'a que faire de l'implémentation car on utilise les méthodes de base défini dans l'interface Map.
:arrow: La déclaration du type de la variable est importante car on va se baser dessus pour tous les traitements effectué sur cette variable...
a++
Hello,
Je vote pour pour toutes les raisons évoquées ci-dessus.
Concernant la suppression des <>, je suis partagé.. Cela peut prêter à confusion dans le code. De plus, l'affichage de warning serait du coup plus suptile et difficile à interpréter.
Pour. J'ai bien le sentiment de n'ajouter qu'un grain de sable dans le quasi consensus sur ce debat mais je ne vois aucune raison de ne pas enrichir Java dans ce sens, compte tenu de ce que cela améliore sensiblement la lisibilité du code.
Bolla
dans l'exemple qui est donné je ne suis pas tellement gêné par la répétition, c'est plus l'absence de désignation de ce générique qui est problématique!
à la place de
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
Je préférai:
generic <String, List<String>> AnagramItem;
...
Map<AnagramItem> anagrams = new HashMap<AnagramItem>();
ce qui permettrait de facilement remplacer un type générique partout,
de faire de l'introspection sur les types génériques ...
Pas vraiment non car pouvoir faire de la reflection suppose que le bytecode stocke quelque part une information sur le type utilise ce qui n'est actuellement pas le cas (dans leur implementation actuelle, les generics ne sont que du sucre syntaxique pre-compilation pour eviter les casts manuels) sans que le programmeur ne s'en charge lui-meme.
Par contre, un typedef ou equivalent n'etait-il pas en discussion pour cette release ou une suivante ???
Je ne vois qu'un seul mauvais point mais il suffit de rendre les 2 écritures possibles pour assurer la compatibilté ...
Perso,
me choque moins queCode:List<String>list = new Arraylist<String>();
C'est pas un gros plus mais il n'y a pas d'inconvénient.Code:List<String> list = new ArrayList();
donc pour :)
Si si, c'est un grand plus:
Un extrait de code dans l'application sur laquelle je travaille :aie:Code:
1
2
3
4 private GenericCache<GenericTripleKey<Long, Long, Long>, DateVals<List<Data>>> fillCache = new GenericCache<GenericTripleKey<Long, Long, Long>, DateVals<List<Data>>>( 100, 0);
Ce qui me choque moi, ce cas de figure (extrême, je l'admets, mais tout de même) :
Code:
1
2
3
4
5 List<String> chaines = new ArrayList(); chaines.add(...); chaines.add(...); ... Set<Date> dates = new TreeSet(new HashSet(new LinkedHashList(new LinkedList(chaines))));
Qu'en penser ? La vérification se fait sur le TreeSet attribué à dates et non en amont, tandis qu'avec la déclaration explicite c'est bien plus compréhensible au premier coup d'œil et le compilateur pointe très précisément du doigt l'erreur.
Bonjour
Je ne veux pas que l'on rajoute des choses dans la syntaxe de Java. Ca va devenir aussi difficile à lire que du C++ tout ça pour faire plaisir à ceux qui voudraient que Java ressemble à C#. Que Java reste Java, je demande à Sun de corriger les bugs, et de les corriger même sous Linux! Je voudrais tout simplement que Java 1.7 soit plus stable et plus rapide encore. Un des principaux avantages de Java est la syntaxe simple. Tout ce que je vois là ne fait que compliquer la lecture pour un gain minime voire nul alors arrêtez ce massacre!
Bonjour,
Humm ... par ce que tu trouves que ça:
ça complique le langage :koi:
J'aurais pu comprendre parfaitement ton point de vue lors de l'introduction des Generics en Java (surtout les Wildcards), mais là, il s'agit de simplifier ça, à moins que tu ne te trompes de post :aie:
Pour, la verbosité parfois excessive étant à mon avis l'un des handicaps de java la suppression de syntaxe redondante me semble un pas dans la bonne direction.
Mais j'ai hésité entre l'avantage de simplifier la lisibilité, et de complexifier la compréhension de la grammaire Java (de moins en moins accessible)
Dans l'idée de déclarer et instancier en une seule instruction j'avais aussi pensé à la syntaxe VB/LotusScript, qui a cependant ton inconvénient N°1: de ne pas utiliser d'interface:
De toutes façon, je trouve que c'est une peu du "sucre" syntaxique,Code:
1
2
3
4
5
6 // pseudo VB de LotusScript dim session as new Session() //transposé en Java Generics new HashMap<String,Person>(10) annuaire;
est-ce qu'on ne pourrait pas carrément avoir un précompilateur comme en C, avec des des %Define et des typedefs, pour alléger les types trops longs à écrire?
ça remplirait finalement la même fonction.
Humm . Je suis contre cette évol du langage. L'intérêt est vraiment mineur et ça complexifie le langage (code plus lisible mais langage plus complexe).
Pour moi, seules les évolutions vraiment utiles doivent être intégrées.
Je suis d'acord avec LeGritche, l'interet est mineur, alors ne compliquons pas.
contre, l'apport de l'innovation ne change pas grand chose, même rien du tout. on a pris l'habitude de travailler ainsi.
Je suis contre, tant qu'il y a la mécanique d'autocomplétion dans la majorité des IDEs, cette forme d'instantiation ne va ajouter que de difficultés au niveau de la lisibilité du code et le rendre moins compréhensible sur tout quand elle est loin de la déclaration de la référence.
Bonjour adiGuba,
Dans ce cas, je vote pour. et ça sera pratique, et le code sera moins lourd, au niveau LECTURE.Citation:
De la manière dont je l'ai compris, ce ne serait possible que dans le cas d'une instantiation en ligne... un peut comme pour les tableaux :
POUR :)
Je m'explique :
L'instanciation ne suit la déclaration que dans des cas simples.
S'ils sont séparés :
on est obligé de retrouver la déclaration pour connaître le type de la liste (sauf avec un puissant IDE).Code:
1
2
3
4List<String> lst; (... code ...) lst = new ArrayList<>();
Si quelqu'un doit se plonger dans du code qu'il n'a pas écrit, l'interprétation doit être sans ambiguïté.
Il faut de toute façon conserver la syntaxe actuelle lorsque le type de l'instanciation est différent du type de la déclaration :
Code:
1
2List<? extends MaSuperClass> lst = new ArrayList<MaClass>();
Dans ce cas là la syntaxe ne serait sûrement pas possible.
C'est un peu comme la syntaxe raccourci des tableaux, où l'on peut omettre le type du tableau :
Mais ce n'est possible que sur la déclaration. Si on affecte le tableau plus loin dans le code on est obligé d'utilité la syntaxe complète. Ainsi ceci ne compile pas :Code:
1
2
3 String[] array = { "a", "b", "c" }; // A la place de : String[] array = new String[]{ "a", "b", "c" };
L'intérêt étant d'éviter de dupliquer l'information lorsque c'est possible (lorsqu'il y a affectation en ligne), tout en évitant les ambiguités...Code:
1
2
3 String[] array; // ... array = { "a", "b", "c" };
a++
Avec cette contrainte effectivement ça devient acceptable.
Thanks
C'est fait : cette proposition a été intégré dans Java 7 sous le nom de "diamond syntax".
Pour la petit histoire il s'agit de la première modification du langage de Java 7 ;)
Pour plus d'info : Première modification du langage : Diamond syntax
a++