2009-2010
Université Libre de Bruxelles							                  
Faculté des Sciences Appliquées
Cours INFO-H-405
Prof. H. Bersini

Approfondissement de la programmation orientée objet
INFO-H-405 : TP3 - Introduction à la généricité en Java

J. Roland

Introduction

Les "generics" et les "templates" s'utilisent de manière très similaire comme le montre l'exemple suivant, où une méthode générique affiche une collection d'objets de type T.

	public static <T>void printCollection(Collection<T> c){
		for(Object e : c){
			System.out.println(e);
		}	
	}

Cette méthode peut être utilisée dans le cas d'une liste d'entiers comme suit,

	List<Integer> liste_int = new LinkedList();
	liste_int.add(0);
	liste_int.add(1);
	printCollection(liste_int);

où T est déduit comme étant de type Integer sur base du type du paramètre par le compilateur.

Bien qu'ils s'utilisent de la même manière, nous allons voir dans la suite que les generics et les templates ont des fonctionnalités différentes.

Implémentation

En c++ un code est généré pour chaque type utilisé dans un template. Par exemple List<int> et List<String> génèrent deux codes différents. En Java le type est simplement remplacé par le type le plus général. Ensuite un "cast" est appliqué pour chaque instance.

Template de template

En C++ il faut mettre un espace lorsque l'on écrit list<vector<T> >, car le compilateur peut interpréter >> comme un opérateur. En Java, le compilateur est suffisamment "intelligent" pour tenir compte du contexte.

Contrainte dans la généricité

La gestion des contraintes est une différence importante entre les templates du C++ et les generics de java. En C++, le type est simplement remplacé lorsque le code du template est instancié. En java nous pouvons ajouter des contraintes sur le type. Par exemple, en Java, lorsque l'on déclare List<T extends Shape>, nous demandons explicitement au compilateur de s'assurer que le type T est un sous-type de Shape.

Wildcards

Dans la méthode générique "printCollection", on peut remarquer que l'on répète plusieurs fois <T>, qu'il n'y a pas de containtes sur le type T, et que nous n'utilisons pas réellement le nom de ce type dans cette méthode. Le langage de programmation Java permet d'écrire Collection<?> ce qui peut se traduire comme une collection de "n'importe quoi". Nous pouvons donc écrire plus facilement la méthode générique comme suit,

	public static void printCollection(Collection<?> c){
		for(Object e : c){
			System.out.println(e);
		}	
	}

Exercice 1:

Voici un exemple de l'utilisation de généricité avec une List :

List<Integer> myIntList = new LinkedList<Integer>();
myIntList.add(new Integer(0));
Integer x = myIntList.iterator().next();

Est-ce que vous pouvez faire la même chose sans généricité ? Si oui, pourquoi introduire la généricité en Java ?

Exercice 2:

Pourquoi est-ce que nous ne pouvons pas utiliser :

	public static void printCollection(Collection<Object> c){
		for(Object e : c){
			System.out.println(e);
		}	
	}

Expliquez pourquoi à l'aide d'un exemple.
Exercice 3:

Quelle fonctionnalité des templates n'existe pas dans les generics de Java ? (Indice : allez voir les exercices sur les templates)