Thématiques principales

samedi 14 octobre 2017

Evolution Java 7

Nous voila donc arrivé a la version 7. Cette version, tout comme la version 5 amène ses bouleversements mais dans une optique de simplification. Voyons en quoi.

Globalement je me suis inspirer de l'article de JmDoudou donc si vous voulez des détails, n’hésitez pas a aller le consulter.

Donc dans les grandes lignes, l'idée de cette version de Java est de simplifier et comme souvent, pour simplifier, on change la syntaxe afin de rendre plus lisible le code sauf pour le premier point qui lui consiste a permettre l’écriture des types entiers en binaire. Bon en dehors d'un besoin très spécifique, comme de traiter un protocole très bas niveau... je ne m’entendrais pas sur ce point.

Autre point de réécriture, celui de permettre d'utiliser des anderscores dans les nombres afin de faire des groupes de chiffres et simplifier la lecture.

Exemple:

1
2
3
4
5
int value = 1_146_789;
value = 4_3;
value = 4___3;
value = 0b1001110_10001011_01001101_01000101;
float pi = 3.141_593f;

Comme je l'avais évoqué dans la partie sur les enum  le switch/case n’était pas capable de traiter autre chose que des types primitifs ou des enum. Maintenant ces derniers pourront traiter des String.

Exemple:

1
2
3
4
5
6
7
String s="toto";
switch(s)
{
    case "toto" : toto();break;
    case "titi" : titi();break;
    default: defaut();break;
}


Bon après honnêtement moi les switch/case j'aime pas ça et souvent on peut les éviter par une bonne hiérarchie de classe (et ça va de même avec les if/then/else imbriqué) mais on retraitera de ce genre de sujet.

L’opérateur <>. alors la, clairement, il s'agit de Ze Sucre Syntaxique. En fait il n'apporte que de la lisibilité et c'est franchement pas mal. Je m'explique, le problème est simple, on est partie dans la construction d'une hiérarchie de classe avec un beau pattern composite et op on se dit tiens utilisons des generiques! Dans le principe c'est pas une mauvaise idée, au contraire sauf que souvent on se retrouve a declarer des listes de truc, machin avec des listes de chouettes shumrtz.

Exemple:

1
Map<Integer, Map<String,List<Truc>>> maStructure=new HashMap<Integer, Map<String,List<Truc>>>();

Bon je dis pas j'ai un peu exageré le trait....  quoique.... Enfin et bien l'operateur diamant permet d'ecrire juste:

1
Map<Integer, Map<String,List<Truc>>> maStructure=new HashMap<>();

Et le compilateur fait le reste du travail de résolution des types s'il en est capable et ca marche aussi pour les retours de fonctions:


1
2
3
private static Map<Integer, Map<String,List<Truc>>> titi() {
     return new HashMap<>();
}

Gestion des ressources. Il s'agit de permettre au bloc try de gérer lui-même la fermeture d'une ressource au lieu de devoir le faire via le finally employé jusqu’à la version 6. On aura alors une écriture plus simple, plus lisible et plus fiable avec laquelle on pourra continuer a gérer les erreurs et exceptions éventuelles mais ou la fermeture des flux se fera automatiquement.

Exemple:


1
2
3
4
5
6
7
8
try (BufferedReader bufferedReader = new BufferedReader(new FileReader("monfichier.txt"))) {
    String ligne = null;
    while ((ligne = bufferedReader.readLine()) != null) {
        System.out.println(ligne);
    }
} catch (IOException ioe) {
    ioe.printStackTrace();
}


Enfin pour ceux qui voudront créer leur propre flux compatible avec le bloc try, il faudra implémenter l'interface java.lang.AutoCloseable

La gestion des exceptions a également été revu en java 7, et c'est une bonne chose car cette nouvelle gestion permet une gestion plus concise des anomalies et de leur type leur de reemissions d'exceptions.

En effet, maintenant, un bloc catch peut être défini pour un groupe d'exception possible permettant de factoriser leur traitements et d’éviter la multiplication des blocs:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
try{ //TODO
}catch (Exception1 e1) {
    //TODOX
}
catch (Exception2 e2) {
    //TODOX
}
catch (Exception3 e3) {
    //TODOX
}
finally {
    //TODO
}

devient si les blocs TODOX sont identiques


1
2
3
4
5
6
try{ //TODO
}catch (Exception1 | Exception2 | Exception3 e) {
    //TODOX
}finally {
    //TODO
}


C'est mieux quand même!

Pour la reemissions d'exceptions c'est simple, si vous catcher une exception a l'aide d'un sur-type mais que vous devez la reemettre avec un throw, et bien sur la définition de la méthode (a la suite du mot clefs throws) vous pourrez toujours utiliser la définition de type de l'exception initiale et non de son sur-type, sauf.... si vous imbriquez deux blocs try/catch.... Dans l'absolu ça permet de garder l'information initiale malgré un filtrage "trop globale".

java.nio.Path en remplacement de java.io.File.... bon ca parle de soi-même, c'est pour accéder plus simplement aux chemins comme sait le faire Python.... et oui dans les autres langages on trouve des trucs bien, il faut savoir en tirer parti... et couplé aux classes Files, DirectoryStream, Filter and coe, on obtient toutes les infos pour traiter les fichiers et toutes leurs proprietés. Dommage que ca n'ai pas été fait déjà a la version 6 qui avait déjà tenté une mise a jour.... a oui pour info tout cela s’appelle l'API NIO 2 et en plus elle intègre la possibilité de traité des flux de façon asynchrone.

Sinon encore des updates dans awt/Swing .... je rentre dans le détail?

Ah si! un truc très sympas, l'ajout du package java.lang.invoke qui enrichi la réflexion deja existante avec des capacités de recherche de méthodes en respectant la visibilité. Cela fournira donc des objets, les MethodHandle, sortes de pointeur de fonction sur les méthodes ciblés. Il faudra faire un petit billet dédié a cette API associé a l'API réflexion. Ca sera très intéressant.

L'API de concurrence est peut être l'apport le plus significatif de Java pour cette version. Par contre son utilisation est loin d’être trivial car nécessitant de bien comprendre les conséquences de son utilisation. Ainsi cette API propose via la classe RecursiveTask de diviser le traitement de processus et les repartissant via des Thread dédiés sur les processeurs physiques de la machine. Ceci va permettre d'exploiter au mieux des ressources cependant attention une limitation en terme de synchronisation peu survenir ainsi une division trop élevé d'une tache en sous-tache pourra être contre productive car passant plus de temps a resynchroniser les résultats de Thread qu'a exécuter leur propre tache. A noter que l'approche doit être forcement récursive.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class Fibonacci extends RecursiveTask<Integer> {
    public static void main(final String[] args) {
        final ForkJoinPool p = new ForkJoinPool();
        final Fibonacci f = new Fibonacci(1_000_000_000);
        p.execute(f);
    }
    final int n;
    Fibonacci(final int n) {
        this.n = n;
    }
    @Override
    protected final Integer compute() {
        if (this.n <= 1) {
            return this.n;
        }
        final Fibonacci f1 = new Fibonacci(this.n - 1);
        f1.fork();
        final Fibonacci f2 = new Fibonacci(this.n - 2);
        return f2.compute() + f1.join();
    }
}


Voila un petit tour d'horizon de java 7, on approche de la dernière version officiellement sortie, la version 9 mais il nous reste encore la version 8 qui a apporté une nouvelle fois de nouveaux concepts très important.

Informations complementaires sur java 7

Aucun commentaire:

Enregistrer un commentaire