Generics

Types paramétrés en Java

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Grâce aux generics (types paramétrés ou types génériques), les instances peuvent opérer sur les types bien définis. Cela peut éviter les problèmes d'exploitation du code quand par exemple notre Map prend comme valeur un String tandis qu'elle devrait accepter uniquement les Integer. Regardons comment cette situation se présente sans (méthode without()) et avec (méthode with()) les generics.

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;

public class Generics {
    public static void main(String[] args) {
        without();
        with();
    }

    private static void without() {
        Map intMap = new HashMap();
        intMap.put("a", 3);
        intMap.put("b", 6);
        intMap.put("c", "ao");
        parseMaps(intMap);
    }
  
    private static void with() {
        Map<String, Integer> intMap = new HashMap<String, Integer>();
        intMap.put("a", 1);
        intMap.put("b", 2);
        intMap.put("c", 3);
        parseMaps(intMap);
    }

    private static void parseMaps(Map parsedMap) {
        Iterator it = parsedMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry) it.next();
            Integer v = (Integer) pairs.getValue();
            System.out.println("Short value of " +v+ " : " + v.shortValue());
        }
    }
}

On verra qu'au moment de compilation le compilateur nous affiche un avertissement :

Note: Generics.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

En lancant le code, on reçoit une exception suivante :

Short value of 6 : 6
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        at Generics.parseMaps(Generics.java:34)
        at Generics.without(Generics.java:18)
        at Generics.main(Generics.java:9)

Si l'on remplace Map intMap = new HashMap(); par eeeMap<String, Integer> intMap = new HashMap<String, Integer>();, au moment de compilation on recevra un message d'erreur :

Generics.java:17: put(java.lang.String,java.lang.Integer) in java.util.Map<java.lang.String,java.lang.Integer> cannot be applied to (java.lang.String,java.lang.String)
    intMap.put("c", "ao");
          ^
1 error

Grâce à ce comportement, déjà à ce stade, on peut réduire le nombre de bugs potentiels. Generics facilitent également le travail en équipe. Les nouveaux développeurs qui arrivent sur un projet savent tout de suite quel type de données attend l'application.

Classes et interfaces avec generics

Egalement les classes nouvellement créées peuvent contenir les types paramétrés. Elles prennent alors comme paramètre(s) une lettre en majuscule. Cette régle a été introduite pour éviter des confusions entre un type paramétré et une classe normale.
- E : correspond à un élément. Il est utilisé pout le type des éléments d'une collection (ex : Collection). Il peut être utilisé à la place du T.
- K : correspond à la clé dans le cas d'une interface clé - valeur. Il est utilisé dans les Maps (ex : Map<K, V>)
- N : correspond au nombre.
- T : correspond au type utilisé (Integer, String etc.). Il peut être utilisé dans un formatteur (ex : Formatter). Il peut être utilisé à la place du E.
- V : correspond à la valeur dans le cas d'une interface clé - valeur. Il est utilisé dans les Maps (ex : Map<K, V>)

afficher le code

Bartosz KONIECZNY Informations sur le langage

Une question ? Une remarque ?

*

*

Un conseil MySQL

Vous voulez pouvoir détecter quelles requêtes posent le problème de performance sans vouloir écrire un logger dans un langage côté serveur ?

Tout d'abord il faut activer le logging des requêtes lentes (log_slow_queries dans votre fichier de configuration du MySQL).

Dans un deuxième temps on doit préciser après combien de temps un requête devient lente. Pour faire cela, on va utiliser long_query_time (aussi dans le fichier de configuration du MySQL). En secondes, il précise le temps maximal de l'exécution d'une requête.

Pour en savoir plus, vous pouvez consulter la documentation MySQL sur log_slow_queries.