// no generics (obsolete)
public interface List { ... }
// generic type E
public interface List<E> { ... }
Object
(každý objekt je instancí třídy Object
).// no generics (obsolete)
public interface List { ... }
// generic type E
public interface List<E> { ... }
E
(předem neznámého) typuT
je type, E
je elementE
nahradíme jakoukoliv třídou nebo rozhranímE get1(int index);
Object get2(int index);
get1
vrací pouze objekty, které jsou typu E
— je vyžadován speciální typget2
vrací libovolný objekt, tj. musíme pak přetypovávatboolean add(E o);
E
List numbers1 = new ArrayList();
numbers1.add(1);
numbers1.add(new Object()); // allowed, unwanted
Integer n = (Integer) numbers1.get(0);
List<Integer> numbers2 = new ArrayList<>();
numbers2.add(1);
numbers2.add(new Object()); // won't compile!
n = numbers2.get(0);
numbers1
lze vložit libovolný objektnumbers2
nelze obecný objekt vložit, je nutné vložit čísloList<List<Object>> listOfDifferentLists;
List<Number> numbers = new ArrayList<Number>();
List<Object> general = numbers; // won't compile!
List<? super Number> general2 = numbers; // solution
Do seznamu, který obsahuje nejvýše čísla lze vkládat pouze objekty, které jsou alespoň čísly. |
Generika poskytují nástroj zvaný žolík (wildcard) , který se zapisuje jako <?>
.
List<Number> numbers = new ArrayList<Number>();
List<?> general = numbers; // OK
general.add("Not a number"); // won't compile!
List<?>
říká, že jde o seznam neznámých prvků.null
, který lze přidat kamkoliv.
Abstraktní třída Number reprezentuje numerické primitivní typy (int, long, double, … )
|
Object
:public static void printList(List<?> list) {
for (Object e : list) {
System.out.println(e);
}
}
Nasledující metoda dělá sumu ze seznamu čísel:
public static double sum(List<Number> numbers) {
double result = 0;
for (Number e : numbers) {
result += e.doubleValue();
}
return result;
}
...
List<Number> numbers = List.of(1,2,3);
sum(numbers); // it works
List<Integer> integers = List.of(1,2,3);
sum(integers); // won't compile!
Integer
je Number
a přesto seznam List<Integer>
nelze použít!List<Number>
, řešením je seznam neznámých prvků, které jsou nejvýše čísly.public static double sum(List<? extends Number> numbers) { ... }
List<E>
, např. v metodě addAll
:boolean addAll(Collection<? extends E> c);
Object
.Další použití žolíků:
E
a třídou Object
.Existuje třídění podle:
hashCode()
— na úrovni třídy Object
Number
Integer
public TreeSet(Comparator<? super E> c);
public interface SortedMap<K,V> extends Map<K,V> { ... }
K
je key, V
je value.public TreeMap(Map<? extends K, ? extends V> m);
public TreeMap(SortedMap<K, ? extends V> m);
static <T> void arrayToList(T[] array, List<T> list) {
for (T o : array) list.add(o);
}
list
téhož typu — stačí, aby jeho typ byl nadtřídou typu pole array
.
Např. Integer[] array
a List<Number> list
Integer
je Number
static <T, S extends T> void copy(List<T> destination, List<S> source);
T
spojuje dva parametry metody a přebytečné S
je nahrazené žolíkem:static <T> void copy(List<T> destination, List<? extends T> source);
Metody jsou public , viditelnost je vynechána kvůli lepší přehlednosti.
|
// generic array creation error
public <T> T[] returnArray() {
return new T[10];
}
List<?>[] pole = new List<?>[10];
static Object max(Collection<T> c);
Prvky kolekce musí implementovat rozhraní Comparable
, což není syntaxí vůbec podchyceno.
ClassCastException
!static <T extends Comparable<? super T>> T max(Collection<T> c);
// if generics are removed
static Comparable max(Collection c); // does not return Object!
Signatura metody se změnila — má vracet Object
, ale vrací Comparable
!
Object
kvůli zpětné kompatibilitě.static <T extends Object & Comparable<? super T>> T max (Collection<T> c);
Slidy vychází z materiálů
/