List strings = Arrays.asList("One", "Two", "Three");
Object stringObject = strings.get(0);
String string = (String) stringObject;
List ints = Arrays.asList(1, 2, 3);
Object intObject = ints.get(0);
int number = (int) intObject;
List strings = Arrays.asList("One", "Two", "Three");
Object stringObject = strings.get(0);
String string = (String) stringObject;
List ints = Arrays.asList(1, 2, 3);
Object intObject = ints.get(0);
int number = (int) intObject;
Le développeur assume la responsabilité de la compilation
Possibilité d’exception à l’exécution
Comment améliorer la vérification de type à la compilation ?
Depuis Java 5
Implémentation des classes template en UML
Contraint les types
Contrainte de type indiquée entre chevrons
Obligatoire pour la déclaration
Optionnel pour l’instanciation (Java 7)
// Avant Java 7
List<String> strings = new ArrayList<String>();
// Depuis Java 7
List<String> strings = new ArrayList<>();
List<String> strings = Arrays.asList("One", "Two", "Three");
String string = strings.get(0);
List<Integer> ints = Arrays.asList(1, 2, 3);
int number = ints.get(0);
Vérification à la compilation
Aucune différence dans le bytecode
interface Foo {
void bar(List<String> strings);
void bar(List<Integer> integers); // compilation error
}
interface Foo<T> {
void apply(T t);
}
class Bar1 implements Foo<String> {
public void apply(String string) {}
}
class Bar2<T> implements Foo<T> {
public void apply(T t) {}
}
Integer[] integers = { 1, 2, 3, 4 };
Number[] numbers = integers;
numbers[0] = 3.14; // ArrayStoreException
List<Integer> integers = Arrays.asList(0, 1, 2, 4);
List<Number> numbers = integers; //compiler error
Utilisation d’un type et de ses sous-types
Permet de lire
Mais pas d’écrire !
?
indique un caractère joker
Sous-type de … | Notation |
---|---|
|
|
|
|
List<Integer> integers = Arrays.asList(0, 1, 2, 4);
List<? extends Number> numbers = integers;
int zero = integers.get(0);
Number one = numbers.get(1);
integers.add(5);
numbers.add(6); // compiler error
Utilisation d’un type et de ses super-types
Permet d’écrire
Mais pas de lire !
List<Number> numbers = Arrays.asList(0, 1, 2, 4);
List<? super Integer> integers = numbers;
integers.add(5);
numbers.add(6);
Number one = numbers.get(1);
integers.get(0); // Type Object
public class Pair<K, V> {
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
public class Pair<K, V> {
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Contrainte sur un type dans la signature d’une méthode
Sans que la classe soit générique
Via un paramètre supplémentaire dans la signature
public class Foo {
static <T> T id(T t) {
return t;
}
public static void main(String... args) {
Foo foo = new Foo();
String string = Foo.id("Hello");
}
}
public class Foo {
static <T extends Number> T max(T a, T b) {
if (a.doubleValue() > b.doubleValue()) {
return a;
}
return b;
}
public static void main(String... args) {
int max1 = Foo.max(1, 2);
double max2 = Foo.max(1.0, 2.0);
Number max = Foo.max(1, 2.0);
}
}
public class Collections {
public static <T> void copy(List<? super T> dest,
List<? extends T> src) {
...
}
}
List<? super Integer> dest = new ArrayList<>();
List<? extends Integer> src = Arrays.asList(0, 1, 2, 4);
Collections.copy(dest, src);