12
1 Cours JAVA / Y.Laborde Java : Les types génériques (<T>) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration d’un type générique (3) 1re déclaration simple <T>, <?> (3) 2e décl. : <T extends xxx>, <? extends xxx> (5) 3e décl. : <T super xxx>, <? super xxx> (7) Déclaration multiple <T,U,…> (8) Conventions de nommage (9) Déclaration d’une méthode générique (10)

1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

Embed Size (px)

Citation preview

Page 1: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

1

Cours JAVA / Y.Laborde

Java : Les types génériques (<T>)

LES TYPES GENERIQUES : Introduction (diapo 2)

Déclaration d’un type générique (3) 1re déclaration simple <T>, <?> (3) 2e décl. : <T extends xxx>, <? extends xxx> (5) 3e décl. : <T super xxx>, <? super xxx> (7) Déclaration multiple <T,U,…> (8) Conventions de nommage(9)

Déclaration d’une méthode générique (10)

Page 2: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

2

Cours JAVA / Y.Laborde

<T> : Introduction

Présenté dans J2SE 5.0 (également appelé Java SE 6), ce perfectionnement du système de type longtemps attendu permet :

de générer de multiples déclarations de types, de méthodes ou de constructeurs à l’aide d’une seule déclaration générique,Ex: public class ArrayList<E> … {… public boolean add(E e) {…} public E get(int index) {…} …}

de générer de multiples déclarations de variables sur la base d’un schéma de type générique inféré à la compilation.Ex: ArrayList<Domino> laPioche = new ArrayList<Domino>;

ArrayList<Joueur> lesJoueurs = new ArrayList<Joueur>;

L’avantage qui en résulte est de permettre de disposer d’ensembles dont le type des éléments est contraint.Le Java Collections Framework utilise abondamment des classes déclarées comme des types génériques. Malgré une complexité apparente, ces classes sont très simples d’emploi.Ex: • public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

• public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

• public interface List<E> extends Collection<E>

• public interface Collection<E> extends Iterable<E>

• public interface Iterable<T>Remarques: les types génériques de Java sont proches des Templates du C++ mais, par certains côtés, ils présentent d’importantes différences qu’il est nécessaire d’assimiler.

Voir The Java Tutorials : http://java.sun.com/docs/books/tutorial/java/generics/gentypes.html

Page 3: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

3

Cours JAVA / Y.Laborde

<T> : Déclaration d’un type générique (1)

1. Première SYNTAXE SIMPLE pour déclarer un type générique, comme classe ou interface :

["public" | "private"] "class" <Nom_de_base> '<' <Lettre> '>’ ["extends" …] ["implements" …] {…}

ou ["public" | "private"] "interface" <Nom_de_base> '<' <Lettre> '>’ ["extends" …] {…}Exemple :

/** * Generic version of the Box1 class. */public class Box1<T> {

private T t;

public void add (T t) { this.t = t; }

public T get ( ) { return this.t; } }

Pour instancier un objet :new Box1<Integer>( ) ou new Box1<Boolean>( )

Exemple d’utilisation :public class Box1Demo{

public static void main (String[] args) {

Box1<Number> numberBox1 = new Box1<Number>( );

numberBox1.add (new Integer (10));

Number someNumber = numberBox1.get ( ); // no cast!

System.out.println ("Box1<Number> numberBox1 => "

+ someNumber);

}

}

soit avec une déclaration de référence :Box1<Integer> integerBox1 = new Box1<Integer>( );

Box1<Boolean> booleanBox1 = new Box1<Boolean>( );

OUTPUT: Box1<Number> numberBox1 => 10

Page 4: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

4

Cours JAVA / Y.Laborde

public class Box1<T> {

private T t; public void add (T t) { this.t = t; } public T get ( ) { return t; } }

Autre exemple d’utilisation :

public class Box1Demo{

public static void main (String[] args) {

Box1<Number> numberBox1 = new Box1<Number>( );

numberBox1.add (new Integer (10));

showGenericBox1 (numberBox1);

}

V1: public static void showGenericBox1 (Box1<?> someBox1) {

Number someNumber = (Number)someBox1.get ( ); // cast needed!

System.out.println ("Box1<?> someBox1 => " + someNumber );

}

V2: public static void showGenericBox1 (Box1<?> someBox1) {

System.out.println ("Box1<?> someBox1 => "

+ someBox1.get ( )); // no cast!

}

}

Il est aussi permis de déclarer des références à des types inconnus (avant inférence) !On utilise alors un caractère jocker (wildcard) qui permet de désigner toutes les sortes de Box1<T>

Mais on ne peut retrouver le type de <T> qu’à l’aide d’un cast !Cette technique doit donc être évitée !En effet, si <T> n’est pas un nombre, une exception sera levée !!!

On peut tout de même s’affranchir du cast ! Mais il n’est alors possible d’utiliser l’objet de type inconnu <T> que comme un Object !ICI: le compilateur traduit l’usage de someBox1.get ( )

en someBox1.get ( ).toString()

OUTPUT: Box1<?> someBox1 => 10OUTPUT: Box1<?> someBox1 => 10

<T> : Déclaration d’un type générique (1)

Page 5: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

5

Cours JAVA / Y.Laborde

<T> : Déclaration d’un type générique (2)

2. Deuxième syntaxe pour déclarer un type générique, comme classe ou interface :

["public" | "private"] "class" <Nom_de_base> '<' <Lettre> "extends" <Type ou Interface> '>’

["extends" …] ["implements" …] {…}

ou ["public" | "private"] "interface" <Nom_de_base> '<' <Lettre> "extends" <Type ou Interface> '>’

["extends" …] {…}

où "extends" a un sens général qui convient aussi bien pour « extends » que pour « implements ».

Exemple :

public interface IAnimal {public void setName (String name);public String getName ();

}/** * Generic version of the Box2 class. */public class Box2<T extends IAnimal> {

private T t;

public void add (T t) { this.t = t; } public T get ( ) { return this.t; }

}

public abstract class Animal implements IAnimal {private String name;// Constructorpublic Animal(String name) { this.name = name; }// overridepublic String toString ( ) { return this.name; }// IAnimal method implementationspublic String getName ( ) { return this.name; }public void setName (String name) { this.name = name; }

}

public class Lion extends Animal {public Lion(String name) { super(name); }

}

public class Butterfly extends Animal {public Butterfly(String name) { super(name); }

}

Page 6: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

6

Cours JAVA / Y.Laborde

public class Box2Demo {

public static void main (String[] args) {

Box2<Lion> lionBox2 = new Box2<Lion>( ); lionBox2.add (new Lion ("Simba"));

Box2<Butterfly> butterflyBox2 = new Box2<Butterfly>( ); butterflyBox2.add (new Butterfly ("Citronade"));

Box2Demo.showAnimalInBox2 (lionBox2); // Show animal from a Box2<Lion>Box2Demo.showAnimalInBox2 (butterflyBox2); // Show animal from a Box2<Butterfly>

}

public static void showAnimalInBox2 (Box2<? extends IAnimal> animalBox2) {

IAnimal someAnimal = animalBox2.get( ); // no cast!

System.out.println ( "Box2<? extends IAnimal> animalBox2 => " + someAnimal.getName( ) + " : “ + someAnimal.getClass( ).getName( ) );

}}

Ajout d’un Lion dans une Box2<Lion>

Ajout d’un Papillon dans une Box2<Butterfly>

La méthode utilise un type générique avec un caractère jocker (wildcard) pour recevoir toutes les sortes de Box2<T> où T implemente au moins un IAnimal

OUTPUT:Box2<? extends IAnimal> animalBox2 => Simba : samplesgenerics.LionBox2<? extends IAnimal> animalBox2 => Citronade : samplesgenerics.Butterfly

<T> : Déclaration d’un type générique (2)

Page 7: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

7

Cours JAVA / Y.Laborde

3. Troisième syntaxe pour déclarer un type générique, comme classe ou interface :

["public" | "private"] "class" <Nom_de_base> '<' <Lettre> "super" <Type ou Interface> '>’

["extends" …] ["implements" …] {…}

ou ["public" | "private"] "interface" <Nom_de_base> '<' <Lettre> "super" <Type ou Interface> '>’

["extends" …] {…}

où "super" a un sens général qui convient aussi bien pour les classes que les interfaces.Le type générique <T extends IAnimal> signifie que le type inféré doit relever AU MINIMUM d’une sorte de IAnimal, c-à-d qu’il doit implémenter l’interface IAnimal ou ses sous-interfaces.

Le type générique <T extends Animal> signifie que le type inféré doit relever AU MINIMUM d’une sorte de Animal, c-à-d qu’il doit être de la classe Animal ou de l’une de ses sous-classes.

D’une manière équivalente, le type générique <T super Animal> signifie que le type inféré doit relever AU MAXIMUM d’une sorte de Animal, c-à-d qu’il doit être de la classe Animal ou de l’une de ses super-classes.

De plus, l’usage d’un caractère jocker est permis comme dans :<? extends Animal> ou <? super Animal>.

<T> : Déclaration d’un type générique (3)

Page 8: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

8

Cours JAVA / Y.Laborde

Un type générique peut être déclaré à l’aide de multiples paramètres de types génériques.Mais chacun doit être unique à l’intérieur de sa déclaration de classe ou d’interface.

La déclaration de Box<T,U> est correcte.

Par contre, la déclaration de Box<T,T> génèrera une erreur sur la seconde occurrence de T.Exemple :

/** * Generic version of the Box3 class. */public class Box3< T , U > {

private T t;

private U u;

public void addT (T t) { this.t = t; }

public T getT ( ) { return this.t; }

public void addU (U u) { this.u = u; }

public U getU ( ) { return this.u; } }

<T> : Déclaration multiple

Page 9: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

9

Cours JAVA / Y.Laborde

<T> : Type générique - Conventions

Conventions usuelles de nommage du paramètre de type (Java SE API) :

Par convention, les noms des paramètres de type sont de SIMPLES LETTRES en MAJUSCULE.

Sans cette convention, il serait très difficile de différencier un type variable du nom d’une classe ou d’une interface ordinaire.

Les noms les plus communément utilisés dans l’API Java sont :<Lettre> Signification Utilisés pour désigner

T Type types quelconques

E Element éléments de collections du Java Collections Framework

N Number types devant être des nombres : Integer, Short, Double, …)

K Key clés relatives à des associations (key,value)

V Value valeurs relatives à des associations (key,value)

S,U,V, … 2e, 3e, 4e types

? Type inconnuutilisé seul ou conjointement avec extends (upper bound) ou super (lower bound) suivi d’un type (qui peut également être générique)

Page 10: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

10

Cours JAVA / Y.Laborde

1. Première SYNTAXE SIMPLE pour déclarer une méthode générique :

["public" | … | "private"] ‘

<' <Lettre> '>'

<Type_retourné> <Nom_de_méthode>

'(' [<liste de paramètres formels utilisant le type générique>] ')' { <corps de la méthode utilisant le type générique> }

Exemple simple :

/** * Generic version of the Box4 class. */public class Box4<T> {

private T t;

public void add (T t) { this.t = t; } public T get ( ) { return this.t; }

public <U> void inspectBox4 ( U u ) {System.out.println ( "U: " +

u.getClass().GetName() );System.out.println ( "T: " +

t.getClass().GetName() );}

}

OUTPUT:T: java.lang.IntegerU: java.lang.String

Exemple d’application :

public class Box4Demo {

public static void main (String[] args) {

Box<Integer> integerBox

= new Box<Integer>( );

integerBox.add (new Integer(10));

integerBox.inspect Box4 ("some text");}

}

OUTPUT:T: java.lang.IntegerU: java.lang.String

<T> : Déclion de méthode générique (1)

Page 11: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

11

Cours JAVA / Y.Laborde

Exemple plus réaliste dedéclaration d’une méthode

générique :/** * Generic version of the Cage class. */public class Cage<T> {

private T t;

public void add (T t) { this.t = t; } public T get ( ) { return this.t; }

// Remplissage des cages d'une liste de cages // avec un objet upublic static <U> // => méthode génériquevoid fillBoxes (List<Cage<U>> cages, U u) {

// Itérer sur les cages de la liste de cagesfor (Cage<U> cage : cages)

// Ajouter l'objet u dans la cage{ cage.add (u); }

}// overridepublic String toString ( )

{ return "Cage(" + this.t.toString ( ) + ")"; }}

public class CageDemo {

public static void main (String[] args) {// Table des noms de lionsString[] lionNames = {"Mufasa","Simba","Nala","Scar"};// Créer une liste de lions (vide)List<Lion> listLions = new ArrayList<Lion>( );// Remplir la liste de lions en instanciant des lions// par itération de la table des noms de lionsfor(String lionName : lionNames)

{ listLions.add (new Lion(lionName)); }// Créer une liste de cages de lion (vide)

List<Cage<Lion>> listCages = new ArrayList<Cage<Lion>>( );// n : nombre aléatoire dans [0,nombre de lions[int n = (int)(Math.random()*lionNames.length);// Ajouter n cages de lion (vides) dans la liste de cagesfor ( int i = 0 ; i <= n ; i++)

{ listCages.add (new Cage<Lion>( )); }// Remplir toutes les cages de la liste de cages// avec un même lion obtenu aléatoirementCage.<Lion>fillBoxes (listCages, listLions.get(n));// Afficher le contenu de la liste de cagesSystem.out.println (listCages);

}}

Méthode générique

Invocation de la méthode générique statique(<Lion> est optionnel)

QUEL EST L’AFFICHAGE

PRODUIT ?

OUTPUT: [Cage(Mufasa)]ou [Cage(Simba), Cage(Simba)]ou etc.

<T> : Déclion de méthode générique (2)

Page 12: 1 Cours JAVA / Y.Laborde Java : Les types génériques ( ) LES TYPES GENERIQUES : Introduction (diapo 2) Déclaration dun type générique (3) 1re déclaration

12Java : Les types génériques (<T>)

Cours JAVA / Y.Laborde

Vous pouvez compéter cette formationà l’aide du tutoriel Java :

http://java.sun.com/docs/books/tutorial/java/generics/gentypes.htmlou (plus avancé)

http://java.sun.com/docs/books/tutorial/extra/generics/index.html