Thématiques principales

vendredi 13 octobre 2017

Evolution Java 5

Suite a quelques échanges professionnel sur Java, je me suis dit qu'il ne serait pas si mal de faire un petit topo illustré de l’évolution de Java avec quelques exemples. Je me suis inspiré de l'article du blog de Xebia qui liste l'ensemble des évolutions majeures du langage au debut de son histoire. Pour le consulté ici

Je ne vais pas traiter les évolutions antérieur a Java 5 car la version 1.4 a été l'age de raison en fournissant l'essentiel de ce que l'on de l'API Java et de sa syntaxe. Pour rappel, l'API java 1.4 se constituait de ceci:



Apports de Java 5:

Bien sur les génériques!  C'est forcement ce que l'on en retient le plus. Souvent comparés aux Templates c++, les deux sont fondamentalements differents. Par exemple, les génériques Java sont résolus lors de l’exécution alors que les templates c++ le sont a la compilation. Ils ont amener beaucoup de complexité dans la manipulation du typage mais ils ont aussi permis la simplification de l’écriture de code qui initialement impliquer d'utiliser des cast et des instanceof.

voici un petit exemple mais pour ceux qui en veulent plus je vous conseille les cours suivants d'openclassroom et de jmdoudou.

 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 class GeneriqueTest<T> {

    private T truc;

    public GeneriqueTest(T truc)
    {
        this.truc=truc;
    }
    
    public T getTruc() {
        return truc;
    }

    public void setTruc(T truc) {
        this.truc = truc;
        
    }
    
    public <S> S functionGen(S s)
    {
        return s;
    }
    
}

L'autoboxing/unboxing qui permet la construction a la volée d'un Wrapper lors de la manipulation d'une variable primitive comme d'un entier ou réciproquement de récupérer automatiquement un entier primitif a partir de son Wrapper. Cette pratique nécessite des précautions car elle masque la création de l'objet Wrapper et généralement tout ce qui est implicite est dangereux  si l'on ne comprend pas le fonctionnement sous-jacent.

Exemple:

1
2
3
4
5
6
7
List<Integer> l=new ArrayList<Integer>();

public int addInt(int i)
{
    l.add(i);
    return l.get(0); 
}

Les imports statiques qui a mon sens si elles permettent de simplifier l’écriture ne facilitent pas forcement la relecture du code si plusieurs imports statique sont employés en même temps. Un abus sera probablement une erreur, une utilisation avec parcimonie une bonne idée.

On écrira

1
System.out.println(PI); 

a la place de

1
System.out.println(Math.PI); 

en ajoutant  

1
import static java.lang.Math.PI; 

en tête de fichier.

Les varargs permettent la définition de fonctions comportant un nombre indéfini de paramètres d'un même type. Il ne s'agit ici que d'un sucre syntaxique équivalent a l'emploie explicite d'un tableau.

Ainsi le code suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public static int sum(int[] values)
{
    int result=0;
    for(int i=0; i< values.length;i++)
        result+=values[i];
    return result;
}

public static void main(String[] args)
{   
    int[] ta1={1,2,3,4,5,6};
    int[] ta2={1,2,3,4,5,6};
    System.out.println(sum(ta1));
    System.out.println(sum(ta2));
}

deviendra:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public static int sum(int ... values)
{
    int result=0;
    for(int i=0; i< values.length;i++)
        result+=values[i];
    return result;
}

public static void main()
{
    System.out.println(sum(1,2,3,4,5,6));
    System.out.println(sum(1,2,3));
}

Les annotations ont été une évolution majeure de Java 5 au même titre que les générique. A ce titre, elles permettent l'ajout de méta-données sur les éléments du code (Classes, méthodes, ou données membres) en vue de traitements spécifiques soit a la compilation (génération de code ou de fichier de configuration) ou au runtime via l'introspection. Un article dédié serait nécessaire pour en faire le tour (tout comme pour les génériques au passage) et ce n'est pas le but. Cependant il faut en retenir que les annotations permettent la décoration du code tout comme le faisait XDoclet mais permettent d'aller franchement plus loin et y associant également des comportements via les processeurs d'annotation.

Petit exemple sur une méthode afin d'en supprimer le warning a la compilation:

1
2
3
4
5
@SuppressWarnings(value = { "static-method" })
public <S> S functionGen(S s)
{
    return s;
}

La simplification des boucles est la aussi un sucre syntaxique, mais celui ci est vraiment pratique car sans ambiguïté. La nouvelle écriture permet de se passer de l'utilisation de l'iterateur issu de la liste sur laquelle on veut itérer.

Ainsi si en Java 1.4 on aurait ecrit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
List l=new ArrayList();
Iterator it=l.iterator();
for (;it.hasNext();)
{
    Object o=it.next();
    if(o instanceof Truc)
    {
        Truc c=(Truc)o;
        c.montruc();
    }
}

en java 5 on écrira plutôt (a noter l'utilisation intéressant du générique pour éviter l'emploie du instanceof)

1
2
3
4
5
List<Truc> l=new ArrayList<Truc>();
for (Truc c:l)
{
    c.montruc();
}

Il faut admettre que c'est plus court... et autre chose bien c'est que ça marche également sur les tableaux

1
2
3
4
5
Truc[] l = {new Truc(),new Truc()};
for (Truc c:l)
{
    c.montruc();
}

Et enfin les enumerations. La aussi nous sommes face a un gros changement dans Java. Elles constituent la dernière grosse évolution de Java 5. Le besoin des enum est venu du problème a déclarer en java 1.4 un ensemble fini de valeur possible sauf en déclarant des constantes. Et encore, il devient vite lourd de devoir créer un objet spécifique ne pouvant prendre que les valeurs définies par ces constantes.

Les enumerations permettent de consolider cela en limitant pour un objet de type enum les valeurs qu'il peut prendre:

1
2
3
4
5
public enum MaCouleur {
    BLANC,BLEU,ROUGE
}

MaCouleur b=MaCouleur.BLANC;

En plus de cela, la construction de certaines structures s'en trouve simplifier comme dans l'emploi du switch/case (a noter qu'il faut attendre la version 7 de java pour pouvoir utiliser des objets dans un switch/case mais nous y reviendrons).

A noter qu'une enum vue par le compilateur n'est qu'une classe héritant de la classe java.lang.Enum. Je vous passe la transformation réalisée par le compilateur mais il est intéressant de savoir que du coup il est possible d'ajouter des comportement a notre enumeration.

Exemple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public enum MaCouleur {
    BLANC("white"),BLEU("blue"),ROUGE("red");
    
    private final String trad;
    
    private MaCouleur(String trad)
    {
        this.trad=trad;
    }

    public String inEnglish()
    {
        return this.trad;
    }
}

On  pourrait aller plus loin en décrivant le mécanisme de classe interne/anonyme permettant de spécifier des comportements spécifiques pour chaque valeur de l'enum. Cependant ce n'est pas le propos de ce billet qui d’ailleurs arrive a sa fin. Le prochain traitera de Java 6.

JMX : Java Management Extension qui est une API intégré de façon standard afin de faciliter la supervision et le monitoring des applications Java. L'exemple le plus simple de son utilisation est lorsque l'on cherche a exploiter les consommations mémoires et CPU d'une JMV a l'aide d'outils tels que la JConsole ou JVisualVM qui se connectent en JMX Remote sur le processus a l'aide de son PID.

Aucun commentaire:

Enregistrer un commentaire