Des nouveautés de java 1.5 Types énumérés Ce qui est fourni... Nouveautés package coin; public enum Coin { penny(1,CoinColor.copper), nickel(5,CoinColor.nickel), dime(10,CoinColor.silver), quarter(25,CoinColor.silver); types énumérés, “autoboxing”, méthode name() et ordinal(), forme syntaxique du for type for-each, factory valueOf(String), méthodes d’arité variable, tableaux des valeurs values(), entrées-sorties, compareTo (un type énuméré implements Comparable) ֒→ ordre de déclaration des constantes (nb : la méthode est final) type générique Types énumérés Ajouter des attributs et des méthodes private Coin(int value, CoinColor color) { this.value = value; this.color = color; } private final int value; private final CoinColor color; sérialisation/désérialisation (un type énuméré implements Serializable) public int getValue() { return this.value; } public CoinColor getColor() { return this.color; } private enum CoinColor { copper, nickel, silver } } USTL http://www.lifl.fr/∼routier 2 USTL 4 http://www.lifl.fr/∼routier Des nouveautés de java 1.5 USTL http://www.lifl.fr/∼routier Types énumérés enum 6 Types énumérés Premier exemple package saison; public enum Saison { permet de définir des (vrais) types énumérés, hiver, printemps, ete, automne; //================================================================ public static void main (String[] args) { les constantes sont des instances du type défini, Saison value = Saison.valueOf(args[0]); possibilité d’utiliser la structure switch sur les valeurs du type, switch(value) { case hiver : System.out.println(" hiver "+ete.compareTo(value)); break; case printemps : System.out.println(+" printemps "+ete.compareTo(value)); break; case ete : System.out.println(" ete "+ete.compareTo(value)); break; case automne : System.out.println(" automne "+ete.compareTo(value));break; } Comparable c = Saison.ete; System.out.println(c.getClass()); for (int i = 0; i< Saison.values().length; i++ ) { Saison v = Saison.values()[i]; System.out.println( " -> "+ v.name()+" : "+ v.ordinal()); } ce qui est mis en place correspond à ce qui a été vu en cours, mais toute la “logistique” est faite automatiquement... Java 1.5 } ---------------------------------------------------------------------javac -d ../classes saison.Saison.java public enum Saison { hiver, printemps, ete, automne } java saison.Saison hiver hiver 2 class saison.Saison -> hiver :0 -> printemps : 1 -> ete : 2 -> automne : 3 Saison s = Saison.hiver; USTL http://www.lifl.fr/∼routier 1 USTL http://www.lifl.fr/∼routier 3 USTL java saison.Saison ete ete 0 ... http://www.lifl.fr/∼routier 5 Autoboxing AutoBoxing Arité variable Arité variable Types génériques Types génériques method(Type ... id) : 0 à n arguments de type T revient (sf syntaxe appel) à method(T[] id) Faciliter les conversions d’un type primitif vers le type objet associé (et respectivement) public class TestVarArgs { public void ms(String ... args) { for(String s : args) System.out.print(s+"."); System.out.println("+"); } public void mi(String a, int ... args) { for(int i : args) System.out.print(i+"."); System.out.println("+"); } //---------------------------------------------------------------------public static void main(String[] args) { TestVarArgs t = new TestVarArgs(); +================================= t.ms("tim","oleon"); | tim.oleon.+ t.mi("a",1,2,3); | 1.2.3.+ t.ms("ti","mo","leon"); | ti.mo.leon.+ t.mi("a",1,2,3,4,5); | 1.2.3.4.5.+ t.ms(); | + } }// TestVarArgs Alléger la syntaxe (appel de constructeurs/méthodes (xxxValue())) Integer i = new Integer(10); int j = i; Integer k = 12; USTL 8 http://www.lifl.fr/∼routier USTL http://www.lifl.fr/∼routier Types énumérés Méthodes différenciées pour chaque constante package operation; import java.util.*; public enum Operation { plus { public double eval(double }, minus { public double eval(double }, times { public double eval(double }, divided by { public double eval(double }; x, double y) { return x + y; } for (Type id : Statement x, double y) { return x - y; } // lecture sur entrée standard Scanner sc = Scanner(System.in); // bloquant int i = sc.nextInt(); // lecture de type primitif dans un fichier Scanner sc = Scanner(new File("myNumbers")); while (sc.hasNextLong()) { long aLong = sc.nextLong(); } // utilisation de délim déf par une exp régulière java.util.regex.Pattern String input = "1 fish 2 fish red fish blue fish"; Scanner s = Scanner(input).useDelimiter("\\s*fish\\s*"); +--------System.out.printf("%d %d\n",s.nextInt(), s.nextInt()); | 1 2 System.out.println(s.next()); | red System.out.println(s.next()); | blue s.close(); Collection c = ...; for(Object o : c) { System.out.println(o); } 7 USTL Entrées-sorties Permet de récupérer des chaı̂ne de caractères ou types primitifs. Décomposition en token à l’aide d’un motif (par défaut espace), comportement “à la itérateur” int[] tabInt = ...; int somme = 0; for(int e : tabInt) { somme = somme+e; } java operation.Operation 6 3 6.0 plus 3.0 = 9.0 6.0 minus 3.0 = 3.0 6.0 times 3.0 = 18.0 6.0 divided by 3.0 = 2.0 12 http://www.lifl.fr/∼routier java.util.Scanner Expression) Exemples : } http://www.lifl.fr/∼routier USTL voir javadoc... Expression est un tableau ou une instance de java.lang.Iterable x, double y) { return x / y; } Avantage : renforcer le typage (dès la compilation) printf() Pour parcourir une collection ou un tableau. x, double y) { return x * y; } permettre de définir des types paramétrés par d’autres types Un for-each for à la for-each public abstract double eval(double x, double y); //---------------------------------------------------------------------public static void main(String args[]) { double x = Double.parseDouble(args[0]); double y = Double.parseDouble(args[1]); for (int i = 0; i < Operation.values().length; i++) { System.out.println(x + " " + op + " " + y + " = " + Operation.values()[i].eval(x, y)); } } USTL 10 Types “paramétrés” / templates. http://www.lifl.fr/∼routier 9 USTL http://www.lifl.fr/∼routier 11 Types génériques Sous-types et génériques Types génériques Joker borné public abstract class Shape { public abstract void draw(Canvas c); } public class Circle extends Shape { public void draw(Canvas c) { ... } } public class Rectangle extends Shape { public void draw(Canvas c) { ... } } public class Canvas { public void draw(Shape s) { s.draw(this); } } Collection<String> n’est pas un sous-type de Collection<Object> ArrayList<String> est un sous-type de Collection<String> Conséquence, soit : public void dump(Collection<Object> c) { for (Object o : c) { System.out.println(o); } } Types génériques Méthode générique méthode paramétrée par un type Dans la classe Context ajouter une méthode addValue qui prend l’identifiant et une valeur du type qui paramètre Value<T> : public <T> void addValue(String id,T value) { Value<T> v = new Value<T>(value); this.addVariable(id, v); } //-----------------------------------------Context c = new Context(); c.addValue("var3",10); c.addValue("var4",true); Quelle signature pour une méthode drawAll qui dessine toutes les Shapes : public void drawAll(???? shapes) { for (Shape s : shapes) { s.draw(this); } } ne peut pas prendre pour paramètre autre chose qu’une Collection<Object> xxx.dump(new ArrayList<Hobbit>()) ne compile pas ! drawAll(List<Shape> shapes) est trop précis : car refuse List<Circle> drawAll(List<?> shapes) est trop vague, car accepte List<String> Collection<Object> ne signifie pas “n’importe quelle collection pourvue qu’elle contienne des objets” mais bien “collection d’Objects” Ce que l’on veut : “Collection de n’importe quoi de type Shape” drawAll(List<? extends Shape> shapes) NB : extends même pour interfaces, super existe aussi USTL http://www.lifl.fr/∼routier 14 USTL http://www.lifl.fr/∼routier Types génériques 16 package value; public class Value<T> { private T v; public Value (T v){ this.v = v; } public T getValue() { return this.v; } }// Value Collection<?> (collection d’inconnus) List<String> l = new ArrayList<String>(); l.add("timoleon"); l.add("bilbo"); l.add("Smaug"); // l.add(new Integer(1)); La seule garantie sur les éléments c’est que ce sont des Objects public void dump(Collection<?> c) { for (Object o : c) { System.out.println(o); } } // ne compile pas Iterator<String> i = l.iterator(); while(i.hasNext()) { String s = i.next(); // pas de cast nécessaire System.out.println("> "+s); } Types génériques Créer un type générique Comment exprimer “n’importe quelle collection” ? càd le supertype de toutes les collections Possibilité de définir des collections typées 18 http://www.lifl.fr/∼routier Types génériques Jokers Exemples : les collections dans java 1.5 USTL xxx.dump(new ArrayList<Hobbit>()) est légal. package value; public class Context { private Map<String,Value> lesVariables; public Context() { lesVariables = new HashMap<String,Value>(); } public void addVariable(String id, Value var) { lesVariables.put(id, var); } public Value getVariable(String id) { return lesVariables.get(id); } //================================================= public static void main(String[] args) { Context c = new Context(); c.addVariable("v1", new Value<Integer>(12)); c.addVariable("v2", new Value<Boolean>(true)); S.o.p("v1: "+c.getVariable("v1").getClass()); S.o.p("v2: "+c.getVariable("v2").getValue().getClass()); } }// Context Mais : String value = l.remove(0); // pas de cast nécessaire System.out.println(value+" removed"); Collection<?> c = new ArrayList<Hobbit>(); c.add(new Hobbit(...)); // ne compile pas, mauvais typage de add for(String s : l) { // pas de cast nécessaire System.out.println("> "+s); } Trace : v1: v2: class value.Value class java.lang.Boolean (inférence de type) USTL http://www.lifl.fr/∼routier 13 USTL http://www.lifl.fr/∼routier 15 USTL http://www.lifl.fr/∼routier 17 Types génériques Attention Rappel : Le polymorphisme existe toujours !!! Ne pas utiliser les génériques quand le polymorphisme convient. public void recycle(<? extends Recyclable> r) revient à (mais est moins clair que) : public void recycle(Recyclable r) Utiliser les génériques pour renforcer le typage quand le besoin existe. USTL http://www.lifl.fr/∼routier 19