Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Découvrons Java 8 ensemble !


Sujet :

Langage Java

  1. #21
    Membre expérimenté

    Profil pro
    Inscrit en
    décembre 2011
    Messages
    949
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : décembre 2011
    Messages : 949
    Points : 1 742
    Points
    1 742
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Au niveau des nouveaux concepts, il faudra désormais faire avec la boucle d'itération interne.


    Jusqu'à présent on avait affaire à des boucles d'itérations externe, soit en utilisant directement un Iterator, soit en utilisant le for-étendus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    List<String> list = ...
     
    // Itération externe utilisant un Iterator :
    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
    	String value = iter.next();
    	// traitement sur value
    }
     
     
    // Itération externe utilisant un for-étendu :
    for (String value : list) {
    	// traitement sur value
    }
    Par "externe" il est sous-entendu que l'implémentation de la liste n'a aucun moyen de contrôler le déroulement de cette dernière.



    Désormais, l'interface Iterable est doté d'une nouvelle méthode forEach() permettant de parcourir les éléments de manière "interne", ce qui nous donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    list.forEach( (value) -> {
    	// traitement sur value
    });
    La principale différence vient du fait que l'on n'effectue pas directement la boucle. On se contente d'appeler la méthode forEach() en lui passant une expression lambda contenant notre traitement.
    Et en terme de performance (vitesse d’exécution), Il-y-a-t-il un gain ?

  2. #22
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par plawyx Voir le message
    Et en terme de performance (vitesse d’exécution), Il-y-a-t-il un gain ?
    Aucune idée pour l'instant. Je ne me suis pas attardé sur la question.
    Par exemple j'ignore quel est le coût l'appel d'une lambda...


    Par défaut forEach() utilise simplement une boucle for-étendu, mais les implémentation pourront la redéfinir pour un accès plus optimisé vis à vis de leur structure interne.
    Par exemple je sais qu'ArrayList redéfini la méthode pour un accès direct à son tableau interne, ce qui devrait être plus efficace car on évite quelques vérifications "inutiles" lié à l'Iterator...



    Mais le plus gros avantages vient du fait qu'il est alors possible de paralléliser le traitement très simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    list.parallelStream().forEach( (value) -> {
    	// traitement sur value (dans des threads parallel)
    });

    a++

  3. #23
    Membre habitué
    Homme Profil pro
    Inscrit en
    septembre 2013
    Messages
    149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : septembre 2013
    Messages : 149
    Points : 126
    Points
    126
    Par défaut
    Bonjour!

    A propos de la nouvelle syntaxe, je me demandais si l'ancienne "bonne vieille syntaxe" fonctionnera toujours.
    En bref le "(variables) {code}" sera toujours fonctionnel?

  4. #24
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    avril 2002
    Messages
    3 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : avril 2002
    Messages : 3 921
    Points : 11 541
    Points
    11 541
    Par défaut
    Citation Envoyé par plawyx Voir le message
    Et en terme de performance (vitesse d’exécution), Il-y-a-t-il un gain ?
    Pas vraiment. C'est juste une approche différente. Si le sujet t’intéresse et que l'anglais ne te fais pas peur, voici un article très intéressant, qui explique les points forts et les limites de chaque approche.

    Pour info, Rust, un autre langage dont je suis l'évolution, utilisait auparavant uniquement des itérateurs internes. Mais depuis la dernière version, il est passé aux itérateurs externes de préférence, en parti a cause des limites signalées dans l'article.

  5. #25
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    L'itération interne est surtout intéressante via l'API de Stream, qui vient d'ailleurs pallier aux limitations indiqués dans l'article, comme le "non-local return".




    Exemple similaire à celui de l'article : On crée une méthode pour recherche un User via son email.
    Traditionnellement on ferait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        public static User searchByEmail(Collection<User> users, String email) {
            for (User u : users) {
                if (email.equals(u.getEmail())) {
                    return u;
                }
            }
            return null;
        }
    Avec l'itération interne, on serait tenté de reproduire quelque chose de similaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        public static User searchByEmail(Collection<User> users, String email) {
            users.forEach( u -> {
                if (email.equals(u.getEmail())) {
                    return u; // COMPILE ERROR
                }
            });
            return null;
        }
    Sauf que ca ne marche pas.
    A l'intérieur d'une lamba le mot-clef return met fin à la lambda, tout comme les mots-clef break et continue ne peuvent pas impacter une boucle au en dehors de la lambda...

    Du coup ca fait pas mal de limitation vis à vis des boucles traditionnelles.


    Mais en fait il faut passer par les Streams :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        public static User searchByEmail(Collection<User> users, String email) {
            return users.stream()
                    .filter(u -> email.equals(u.getEmail()))
                    .findAny()
                    .orElse(null);
        }
    Explications :
    • filter() permet de filtrer des éléments. Ici on ne prend que les "User" correspondant à l'email indiqué.
    • findAny() effectue la boucle interne (comme forEach), mais en s'arrêtant dès qu'un élément est trouvé.
    • orElse() permet de définir la valeur par défaut si on ne trouve aucun élément



    La grosse différence c'est que l'on n'a plus une instruction pour la boucle, avec laquelle on peut faire un peu tout ce qu'on veut, mais une API qui définit un ensemble de méthode gérant les cas les plus courant.
    Il restera sûrement des cas qui seront pas utilisable via les Streams, mais ca devrait quand même être rare à mon avis...


    Par contre il faudra sûrement un peu de temps avant de bien appréhender tout cela...


    a++

  6. #26
    Membre éprouvé Avatar de atha2
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2007
    Messages
    695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : janvier 2007
    Messages : 695
    Points : 1 222
    Points
    1 222
    Par défaut
    Je n'ai pas encore lu l'article sur la nouvelle API de date mais il y a-t-il un moyen de récupérer simplement une date correspondant au début d'un jour ou d'un heure ?
    Avec l'API actuelle, on est obligé de faire :
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(aDate);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    Date beginOfDayDate = calendar.getTime();
    Ce qui n'est pas très intuitif...

    Edit : La classe LocalDate possède une method atStartOfDay(), par contre celle-ci retourne une LocalDateTime. Je ne suis pas sur de comprendre la différence entre les 2 classes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    // Même date, mais avec les champs inférieur au jour à zéro (donc heure, minutes, secondes, nanosecondes)
    LocalDateTime beginOfDayDate = dtime.truncatedTo(ChronoUnit.DAY);
    Ah oui effectivement c'est beaucoup mieux. Les exemples que tu as postés et un rapide survol de la javadoc m'ont convaincu que cette API est très complète et simple à utiliser

  7. #27
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par atha2 Voir le message
    Edit : La classe LocalDate possède une method atStartOfDay(), par contre celle-ci retourne une LocalDateTime. Je ne suis pas sur de comprendre la différence entre les 2 classes.
    LocalDate représente une date sans la partie "heure".
    LocalDateTime représente une date avec les heures jusqu'au millisecondes.
    Il existe aussi LocalTime qui représente seulement une heure sans la date...

    Il y a plusieurs méthode static permettant de créer des objets dates, exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Date actuelle
    LocalDate dateNow = LocalDate.now();
    // Date/heure actuelle
    LocalDateTime dtimeNow = LocalDateTime.now();
    // 15 aout 2013
    LocalDate date = LocalDate.of(2013, 8, 15);
    // 15 aout 2013 à midi
    LocalDateTime dtime = LocalDateTime.of(2013, 8, 15, 12, 0);

    Ensuite chaque instance possède plusieurs méthodes permettant de créer des objets dérivés (chaque objet est immuable).
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    LocalDateTime dtime = ...
     
    // Obtenir le jour avant :
    LocalDateTime dayBefore = dtime.minusDay(1);
     
    // Redéfinir certains champs :
    LocalDateTime newDtime = dtime.withHour(12).withMinute(0);
     
    // Même date, mais avec les champs inférieur au jour à zéro (donc heure, minutes, secondes, nanosecondes)
    LocalDateTime beginOfDayDate = dtime.truncatedTo(ChronoUnit.DAY);

    Perso l'API me semble vraiment très complète.


    Au passage contrairement à Date, les types Local*** ne sont pas lié à un fuseau horaire quelconque (ce qui peut induire en erreur si on ne le prend pas en compte).

    Il y a d'autre type si l'on a besoin de gérer cela (par exemple OffsetDateTime et ZonedDateTime).



    Perso cette API me semble très complète !


    a++

  8. #28
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 898
    Points : 7 430
    Points
    7 430
    Par défaut
    Les API date étaient vraiment un de mes grands regrets de report java 7, je suis content de les voir arriver.

    Effectivement je note le côté immutable des classes. Je vois aussi qu'ils ont fait en sorte que tenter de fabriquer une date impossible (31 février) génère immédiatement une exception, je suis content qu'ils aient renoncé à leur "leniency" sur les dates, ça devait être un casse tête à gérer en plus d'être un non sens total.

    Puis les pseudo-constructors statiques de ce style :

    public static LocalDateTime of(int year,
    int month,
    int dayOfMonth,
    int hour,
    int minute)

    me feront très vite oublier l'assemblage de morceaux de date avec cette grosse daube de Calendar et son mois indexé à 0...

    C'est pour moi une des améliorations MAJEURES de java 8 et une solution à des problèmes récurrents.
    Du côté de joda, j'ai toujours déploré que certaines méthodes abusent des exceptions du framework. Par exemple un

    DateTime parseDateTime(String, DateTimeFormatter);

    qui lève un "IllegalArgumentException" lorsque le String n'est pas parseable, j'ai toujours trouvé ça un peu bof. J'aime pas devoir catcher une exception qui indique plutôt une BUG dans l'utilisation d'une API, je préfère une exception *précise*. Je suis content qu'ils aient introduits une exception spécifique DateTimeException pour gérer ce genre de souci.

    Enfin voilà...

    Sinon j'ai noté cette classe discrète mais sympathique :

    http://download.java.net/jdk8/docs/a.../Optional.html

    Elle a l'avantage de signifier clairement l'acceptance ou non du NULL comme valeur en paramètre ou valeur de retour. Malheureusement, je ne pense pas que le JDK fasse lui même suffisamment usage de cette classe pour l'implanter dans nos habitudes, il faudrait aussi l'accompagner d'un sucre syntaxique comme "String?" qui serait équivalent à "Optional<String>".
    Certains soi-disant java-killers ont fait le pari de carrément supprimer la mutabilité et la nullabilité par défaut des réflérences, un choix très judicieux à mon humble avis.

    Pour les lambdas, je me dis que c'est bien car ça va donner à java une partie non des moindres des bénéfices de scala. Même si j'ai un peu peur d'assister à une closurite aigue de la part des développeurs les premiers temps. Un peu comme un gamin privé longtemps de chocolat qui soudain s'empiffre 5 tablettes puis au final se calme parce qu'il fait une indigestion ;-).

    Ca pourrait être que du bonheur, mais si seulement on avait trouvé une solution pour ces conneries de getters setters qui polluent inutilement mes classes.

  9. #29
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _skip Voir le message
    Je vois aussi qu'ils ont fait en sorte que tenter de fabriquer une date impossible (31 février) génère immédiatement une exception, je suis content qu'ils aient renoncé à leur "leniency" sur les dates, ça devait être un casse tête à gérer en plus d'être un non sens total.
    +1

    En fait le mode lenient existe toujours mais n'est plus utilisé par défaut.
    Il y a 3 modes : STRICT, SMART et LENIENT.
    On peut changer de mode via la méthode withResolverStyle()
    • STRICT n'accepte aucune erreur.
      (ex : le 31-avril génère une erreur)
    • SMART, qui accepte certaines petites erreurs de dépassement en s'alignant à la valeur la plus haute qu'elle peut recevoir.
      (ex: Le 31-avril devient le 30-avril, et le 32-avril génère une erreur)
    • LENIENT, qui corrige la date en la décalant.
      (ex: Le 31-avril devient le 01-mai, et le 32-avril devient le 02-mai)




    L'API utilise majoritairement STRICT (sauf pour le format RFC 1123).
    Par contre les DateTimeFormatter utilisent SMART par défaut (par exemple lorsqu'on en crée un via DateTimeFormatter.ofPattern())



    A noter également que le parse() lira toute la chaine, contrairement au SimpleDateFormat qui peut s'arrêter avant s'il trouve ce qu'il veut...



    Citation Envoyé par _skip Voir le message
    Je suis content qu'ils aient introduits une exception spécifique DateTimeException pour gérer ce genre de souci.
    Perso je suis surtout heureux qu'ils aient opté pour des "RuntimeExceptions", afin de ne pas nous obliger à les traiter...



    Citation Envoyé par _skip Voir le message
    Ca pourrait être que du bonheur, mais si seulement on avait trouvé une solution pour ces conneries de getters setters qui polluent inutilement mes classes.
    +1


    a++

  10. #30
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 898
    Points : 7 430
    Points
    7 430
    Par défaut
    J'avais pas vu pour le strict. Bon ça a le mérite d'exister mais au moins ce n'est plus trop tolérant au n'importe quoi par défaut.

    Perso je suis surtout heureux qu'ils aient opté pour des "RuntimeExceptions", afin de ne pas nous obliger à les traiter...
    Oui ça aurait été à peu près aussi nul que de devoir traiter UnsupportedCharsetException quand tu utilises en dur UTF-8 qui est garanti d'exister par la spec java elle-même. Enfin bon, les checked exceptions sont pas prêtes de disparaître.

    L'autre truc auquel je m'attends avec ce java 8, c'est de voir un déclin d'intérêt pour les autres langages de la JVM.

    Sinon pour revenir à mon Optional, il y a des choses intéressantes à faire avec :
    http://nurkiewicz.blogspot.ch/2013/0...eat-sheet.html

  11. #31
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    avril 2002
    Messages
    3 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : avril 2002
    Messages : 3 921
    Points : 11 541
    Points
    11 541
    Par défaut
    Citation Envoyé par _skip Voir le message
    Elle a l'avantage de signifier clairement l'acceptance ou non du NULL comme valeur en paramètre ou valeur de retour. Malheureusement, je ne pense pas que le JDK fasse lui même suffisamment usage de cette classe pour l'implanter dans nos habitudes, il faudrait aussi l'accompagner d'un sucre syntaxique comme "String?" qui serait équivalent à "Optional<String>".
    Certains soi-disant java-killers ont fait le pari de carrément supprimer la mutabilité et la nullabilité par défaut des réflérences, un choix très judicieux à mon humble avis.
    La classe Optional est en théorie une bonne idée, malheureusement, Java reposant lourdement sur l'usage du nul, son usage restera certainement anecdotique. Pour moi, ce n'est vraiment intéressant que si ça permet de bannir le null. Sinon ça rajoute de la verbosité sans fournir de garanties.

    Je pense aussi que l'immutabilité par défaut et l’absence de null, sont des fonctionnalités indispensables pour tout nouveau langage. Malheureusement pour des raison de rétrocompatibilité, ça n'arrivera jamais dans Java.

    Citation Envoyé par _skip Voir le message
    Ca pourrait être que du bonheur, mais si seulement on avait trouvé une solution pour ces conneries de getters setters qui polluent inutilement mes classes.
    C'est vraiment pour moi LE point noir.
    Je n'arrive pas a comprendre qu'ils n'aient pas passé en top priorité des problèmes à résoudre ce boulet qu'on se traine depuis la nuit des temps.

    Citation Envoyé par adiGuba Voir le message
    Perso je suis surtout heureux qu'ils aient opté pour des "RuntimeExceptions", afin de ne pas nous obliger à les traiter...
    Autant être obligé de traiter les CheckedException peut-être lourd, autant je pense que passer uniquement à des RuntimeException est l'excès inverse. On peut vite oublier de traiter un cas d'erreur que l'on ne voit pas directement.
    Je pense qu'un système pour ignorer les CheckedException comme on peut ignorer les warnings aurait été une bonne solution.

  12. #32
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 898
    Points : 7 430
    Points
    7 430
    Par défaut
    Citation Envoyé par Uther Voir le message
    La classe Optional est en théorie une bonne idée, malheureusement, Java reposant lourdement sur l'usage du nul, son usage restera certainement anecdotique. Pour moi, ce n'est vraiment intéressant que si ça permet de bannir le null. Sinon ça rajoute de la verbosité sans fournir de garanties.
    Oui c'est exactement ce que je dis dans mon post, il aurait fallu que le JDK s'en serve lui-même et idéalement qu'il y ait un sucre syntaxique un peu comme en .Net ou

    Int? correspond en réalité à Nullable<Int>.

    Dans le même style, il y aurait les Tuples qui seraient intéressants en remplacement de mini-classes, mais sans les sucres syntaxiques qui vont avec, c'est plus lourd qu'autre chose.

    Je pense aussi que l'immutabilité par défaut et l’absence de null, sont des fonctionnalités indispensables pour tout nouveau langage. Malheureusement pour des raison de rétrocompatibilité, ça n'arrivera jamais dans Java.
    Un java 2.0 ce serait juste trop beau. Effectivement je suis très intéressé par les langages pour la JVM du style ceylon qui font cette différence entre référence mutable et/ou nullable, c'est une énorme sécurité et ça apporte vraiment à la lecture.
    Alors que la mode c'est de dire que les langages dynamiques c'est trop cool et les IDE c'est pour les blaireaux, cela fait toujours plaisir de voir que des développeurs habitués aux gros projets reconnaissent la valeur d'une vérification minutieuse par le compilateur.


    Je n'arrive pas a comprendre qu'ils n'aient pas passé en top priorité des problèmes à résoudre ce boulet qu'on se traine depuis la nuit des temps.
    Je sais pas exactement ce qu'en pense Adiguba mais cela ferait qu'on est en tout cas 2 à la suite à trouver que c'est vraiment un manque impardonnable. Pourtant je vois aussi que pas mal de monde sur les forums dire que "oué mais eclipse en 2 clicks il te génère ça", je veux bien mais ça reste du bruit inutile. Dans java 7 y'avait une proposition en ce sens, mais ils avaient choisi un opérateur "->" assez moche et y'avait le souci de la compatibilité avec l'existant. Il aurait suffit d'une annotation à la lombok qui les génère automatiquement, enfin je me serais contenté de n'importe quoi tellement je hais générer ces méthodes.

    Autant être obligé de traiter les CheckedException peut-être lourd, autant je pense que passer uniquement à des RuntimeException est l'excès inverse. On peut vite oublier de traiter un cas d'erreur que l'on ne voit pas directement.
    Je pense qu'un système pour ignorer les CheckedException comme on peut ignorer les warnings aurait été une bonne solution.
    Oui, perso je ne sais pas trop si la suppression des check est la solution mais il y a de nombreuses checked exception qui pourraient être unchecked. Le cas que j'ai cité plus haut, les ParserConfigurationException en XML et une série d'autres. De plus, bien souvent avec les exceptions, dans 80% des cas, à part s'excuser auprès de l'utilisateur on peut quasiment rien faire, c'est vrai que ça te rend attentif sur la possibilité que ton code soit interrompu de façon abrupte et t'auras moins de mal à te rappeler du besoin d'un finally par exemple.
    Mais bon pour moi, les inconvénients dépassent les avantages.

  13. #33
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    avril 2002
    Messages
    3 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : avril 2002
    Messages : 3 921
    Points : 11 541
    Points
    11 541
    Par défaut
    Citation Envoyé par _skip Voir le message
    Oui c'est exactement ce que je dis dans mon post, il aurait fallu que le JDK s'en serve lui-même et idéalement qu'il y ait un sucre syntaxique un peu comme en .Net ou

    Int? correspond en réalité à Nullable<Int>.
    Le cas de .net n'est pas vraiment meilleur pour moi.
    Le point d'interrogation permet de rendre nullable les types primitifs mais les référence classiques restent nullables même sans point d'interrogation, ce qui fait que le principal problème est toujours là.

    Citation Envoyé par _skip Voir le message
    Dans le même style, il y aurait les Tuples qui seraient intéressants en remplacement de mini-classes, mais sans les sucres syntaxiques qui vont avec, c'est plus lourd qu'autre chose.
    Pour les tuple il faudrait l'équivalent Java des variadic template de C++ mais je n'ose plus en espérer autant d'Oracle depuis bien longtemps.

    Citation Envoyé par _skip Voir le message
    Un java 2.0 ce serait juste trop beau. Effectivement je suis très intéressé par les langages pour la JVM du style ceylon qui font cette différence entre référence mutable et/ou nullable, c'est une énorme sécurité et ça apporte vraiment à la lecture.
    Alors que la mode c'est de dire que les langages dynamiques c'est trop cool et les IDE c'est pour les blaireaux, cela fait toujours plaisir de voir que des développeurs habitués aux gros projets reconnaissent la valeur d'une vérification minutieuse par le compilateur.

    C'est en effet le problème: il y a beaucoup de projet de langages avec certaines bonnes idées, mais je trouve que malheureusement, soit ça va bien plus loin qu'une simple évolution de Java (scala, clojure,...), soit c'est trop peu ambitieux pour justifier l'incompatibilité(ceylon,...) et que du coup les efforts sont assez fragmentés.
    Je pense que Oracle aurait du il y a un moment réfléchir à une sorte de Java++ (le nom marketing de Java 2 ayant déjà été utilisé caractériser les java 1.2 à 1.5). Maintenant ça me parait un peu tard pour envisager ça. Il risquent de continuer a empiler les fonctionnalités rustines encore un moment.

    Personnellement, je regarde de plus en plus du coté des compilateurs hors JVM. Rust même s'il est encore embryonnaire me plait beaucoup dans son approche de la sécurité, même s'il est clairement lui aussi bien au delà du Java classique(je sais je me contredis).

  14. #34
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Je suis tout à fait d'accord en ce qui concerne les property !
    C'est un gros manque.


    A l'époque j'avais un peu suivi les discussions autour de cela autour du projet Coin, et il y avait même plusieurs propositions plus ou moins poussé, mais il n'y a jamais eu de consensus...
    Certains voulaient se contenter du strict minimum (du sucre syntaxique pour générer les getter/setter implicitement).
    D'autres voulaient de vraix properties avec plein de fonctionnalités intégrés (listener, API de reflection, etc.)






    Concernant les checked/unchecked exceptions, je préfère largement les seconds.
    Je considère un peu les checked-exceptions comme une fausse bonne idée du langage.
    C'est en plus une grosse source d'erreur chez les débutant, qui les traitent mal (je préfère plutôt voir remonter une exception !)
    Maintenant avec un moyen de les ignorer comme le propose Uther pourraient amplement me sastisfaire





    Citation Envoyé par _skip Voir le message
    Alors que la mode c'est de dire que les langages dynamiques c'est trop cool et les IDE c'est pour les blaireaux, cela fait toujours plaisir de voir que des développeurs habitués aux gros projets reconnaissent la valeur d'une vérification minutieuse par le compilateur.
    Je fait aussi du développement Web.
    On est en train de passé de javascript avec JQuery à du code généré via GWT (et donc écrit en Java pure - ou presque -).
    C'est le jour et la nuit tellement c'est agréable



    a++

  15. #35
    Membre expérimenté
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    juillet 2006
    Messages
    1 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : juillet 2006
    Messages : 1 152
    Points : 1 626
    Points
    1 626
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Je suis tout à fait d'accord en ce qui concerne les property !
    C'est un gros manque.
    pas tropd'acc.
    les getters/setters systematique, les beans, les POJOS sont une énorme erreur (en général: sauf dans quelque cas particuliers)


    Citation Envoyé par adiGuba Voir le message
    Je considère un peu les checked-exceptions comme une fausse bonne idée du langage.
    pas du tout d'acc.
    Il y a ainsi une distinction claire entre les erreurs "normales" et les "anormales".
    Que ça soit mal utilisé parfois (y compris dans les catalogues de codes) est une autre histoire.
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (un peu de pub pour mon site: http://scrountch.info/java )

  16. #36
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    pas tropd'acc.
    les getters/setters systematique, les beans, les POJOS sont une énorme erreur (en général: sauf dans quelque cas particuliers)
    Tu pourrais approfondir ton propos ?



    Citation Envoyé par professeur shadoko Voir le message
    pas du tout d'acc.
    Il y a ainsi une distinction claire entre les erreurs "normales" et les "anormales".
    Que ça soit mal utilisé parfois (y compris dans les catalogues de codes) est une autre histoire.
    Ce qui me gêne, c'est que cette distinction entre erreurs "normales" et "anormales" est prédéfini quel que soit le cas. Or ce choix devrait aussi dépendre de la manière dont le développeur utilise la méthode en question.

    Par exemple SimpleDateFormat génère des checked-exception lorsqu'on parse une date.
    Si cette date provient d'une saisie utilisateur c'est logique de traiter ces exceptions (car une erreur est si vite arrivé).
    Par contre cette date peut arriver par d'autres flux sous forme de texte (un web-service par exemple), et là la vérification est inutile sauf si le format du webservice est incorrect... et je préfère avoir une exception "propre" dans ce cas !


    Le problème des checked-exceptions, c'est que du coup on peut avoir tendance à faire des try/catch bidon... qui peuvent un jour poser problème.


    En cas de problème, je préfère largement voir une exception remonté la pile d'appel, plutôt que de la voir "traiter" maladroitement.
    Surtout que je met toujours en place un exception-handler pour récupérer la trace de l'erreur.



    a++

  17. #37
    Membre expérimenté
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    juillet 2006
    Messages
    1 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : juillet 2006
    Messages : 1 152
    Points : 1 626
    Points
    1 626
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Tu pourrais approfondir ton propos ?
    question de gout : je déteste les implicites dans un langage même si ça peut le rendre verbeux.
    Exemple de ce que je cherche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    public class CompteEnBanque {
      final int id; // uniquement un get  - mis en place par constructeur
      Client client; // set se discute -mis en place par constructeur
      Montant solde; //certainement pas de set!
      Montant découvertAutorisé ; // get et set sous contrôle
      List<Operation> historique = new ArrayList<>() ; // pas de set NI DE GET!
      List<Operation> visionHistorique = Collections.unModifiableList(historique) ;
      public List<Operation> getHistorique() {
        return visionHistorique ;
      }
     
      // constructeurs
     
     // metier
      public void retrait(Montant montant) throws ExceptionDecouvert, IllegalArgumentException {
       // habilitée  à modifier le solde  et l'historique
      }
     
    }
    pour les exceptions:
    - si le montant passé est négatif -> exception runtime (responsabilité du code appelant)
    - si le retrait est susceptible de dépasser le découvert autorisé -> exception controlée (le code appelant DOIT faire quelque chose -et il n'a pas forcément l'information judicieuse)

    bien sûr le problème c'est que bien des librairies ne respectent pas ces règles et que, du coup, on s'énerve après les exceptions controlées (qui sont pourtant essentielles!)
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (un peu de pub pour mon site: http://scrountch.info/java )

  18. #38
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Le problème pour moi c'est que cette distinction ne peut pas toujours être effectué par le concepteur de la librairie ou de la méthode.
    J'estime que le développeur qui va l'utiliser doit également avoir son mot à dire là dessus !


    On pourrait imaginer par exemple une application qui gèrerait ce "découvert", et bloquerait l'utilisation de la méthode retrait() en conséquence.
    De ce fait l'exception ne devrait jamais survenir. Cela devient la responsabilité du code appelant, et il devient donc inutile de la traiter...
    (mais sa présence est toujours utile pour détecter des bugs).



    Autre exemple avec les IOException :
    • Si l'application doit lire un fichier fournit par l'utilisateur, alors il faut en effet traiter les exceptions, et c'est "normal" que ce soit une exception contrôlée...
    • Par contre pour une application qui doit lire un de ses fichiers de données (config, image, ...), je trouve illogique d'avoir à traiter l'exception.
      Pour moi c'est de la responsabilité du code appelant, ou plus précisément du développeur qui devra packager l'application.




    a++

  19. #39
    Membre expérimenté
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    juillet 2006
    Messages
    1 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : juillet 2006
    Messages : 1 152
    Points : 1 626
    Points
    1 626
    Par défaut
    je ne vois pas pourquoi ce serait incompatible avec une politique qui consiste à dire que dans la chaine correspondant à une initiative il y a quelqu'un qui doit traiter l'exception parce que le code qui la déclenche signale un passage de responsabilité. Bien qu'en général je considère que cela doit remonter à l'initiative initiale il y a bien des cas où la responsabilité est assumée par un agent intermédiaire dans la chaîne et c'est là que c'est clair au niveau de la répartition des tâches. Dans le cas contraire on a des trucs attrape-tout dont le rôle fonctionnel n'est pas bien défini.

    Pour revenir au coeur de tout ça je dirais que j'utilise Groovy et Java dans un grand projet. On voit bien que les stratégies concernant propriétés et exceptions sont bien différentes. Mais chacun reste dans son domaine : dans la partie gérée par de multiples programmeurs (dans différents pays) c'est du Java et je fais une police sévère: j'ai remplacé Spring par un outil maison pour débarasser le projet de tout bean (en prouvant au passage les instabilités de comportement induites par la présence de beans). Je reconnais que je ne suis pas encore arrivé à faire adopter une politique propre en ce qui concerne les exceptions (mais ça viendra). Sur certains parties qui ne sont gérées que par moi et qui sont à la lisière de fonctionnalités de script j'utilise Groovy.
    Ma conclusion: il ne faut pas faire des langages attrape-tout , chacun doit rester avec ses paradigmes adaptées à son contexte d'utilisation.
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (un peu de pub pour mon site: http://scrountch.info/java )

  20. #40
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : avril 2002
    Messages : 13 938
    Points : 23 004
    Points
    23 004
    Billets dans le blog
    1
    Par défaut
    Tiens la classe Files de Java 7 s'est également enrichit des méthodes utilisant les Stream.



    Petit exemple :
    Imaginons qu'on dispose d'une classe User contenant diverse information d'un utilisateur (nom, adresse, email, téléphone, etc.), et d'une méthode User.parse(String) permettant de parser une ligne au format CSV.

    L'objectif étant de charger un fichier CSV afin de lister uniquement les utilisateurs dont l'adresse email n'est pas défini.

    Avec Java 7 on pourrait être tenté d'écrire quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        public static List<User> read1(Path file) throws IOException {
            List<User> users = new ArrayList<>();
            for (String line : Files.readAllLines(file, StandardCharsets.ISO_8859_1)) {
                 // On supprime les espaces inutiles
                 line = line.trim();
                 // On ignore les lignes vides
                 if (line.isEmpty())
                    continue;
                // On ignore les lignes commençant par #
                if (line.startsWith("#"))
                    continue;
                // On crée l'User
                User u = User.parse(line);
                // Et on ne l'ajoute à la liste que si son email est vide
                if (u.getEmail()==null) {
                    users.add(u);
                }
            }
            return users;
        }
    Mais il y a un gros défaut, c'est que Files.readAllLines() retourne une List<String> contenant toutes les lignes du fichiers, ce qui peut s'avérer très gourmand en mémoire si le fichier est conséquent.
    Et c'est particulièrement dommageable ici car on ne va récupérer qu'une partie des informations du fichier.




    Pour éviter cela il faut effectuer la lecture soit même pour traiter les infos lignes par lignes, mais du coup on se tape le code de lecture du fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
        public static List<User> read2(Path file) throws IOException {
            List<User> users = new ArrayList<>();
            try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.ISO_8859_1)) {
                String line;
                while ( (line=reader.readLine()) != null ) {
     
                    // On supprime les espaces inutiles
                    line = line.trim();
                    // On ignore les lignes vides
                    if (line.isEmpty())
                        continue;
                    // On ignore les lignes commençant par #
                    if (line.startsWith("#"))
                        continue;
                    // On crée l'User
                    User u = User.parse(line);
                    // Et on ne l'ajoute à la liste que si son email est vide
                    if (u.getEmail()==null) {
                        users.add(u);
                    }
                }
            }
            return users;
        }



    Avec Java 8 on pourra utiliser un Stream<String> pour récupérer les lignes du fichier.
    On peut ainsi filtrer et transformer les données au fur et à mesure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        public static List<User> read3(Path file) throws IOException {
            // On récupère un Stream<String> représentant les lignes du fichier :
            return Files.lines(file, StandardCharsets.ISO_8859_1)
                     // On supprime les espaces inutiles
                    .map( String::trim )
                     // On ne prend pas les lignes vides
                    .filter( line -> !line.isEmpty() )
                    // On ne prend pas les lignes commençant par #
                    .filter( line -> !line.startsWith("#") )
                    // On convertit le tout en User
                    .map( User::parse )
                    // Et on ne prend que les User sans email
                    .filter( u -> u.getEmail() == null )
                    // Enfin on récupère le tout dans une ArrayList :
                    .collect( Collectors.toCollection(ArrayList::new) );
        }


    Mais le plus fort là dedans, c'est que le code devient par la même occasion parallélisable !
    En effet il suffit d'ajouter .parallel() dans le flux d'appel des méthodes du Stream pour que les traitements soient parallélisé...



    a++

Discussions similaires

  1. Réponses: 4
    Dernier message: 02/12/2011, 18h06
  2. Les ensembles en Java
    Par Malek_moly dans le forum Débuter
    Réponses: 5
    Dernier message: 28/01/2011, 16h29
  3. Réponses: 1
    Dernier message: 17/04/2009, 10h03
  4. [Java 5] Récuperer un ensemble d'annotations
    Par Shogun dans le forum Langage
    Réponses: 2
    Dernier message: 03/10/2007, 13h27
  5. Réponses: 9
    Dernier message: 11/05/2007, 17h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo