Обмеження на Generics
Для ефективного використання Java Generics, необхідно враховувати наступні обмеження:
При створенні Pair object, не можна замінити примітивний тип установка типу K або V :
Можна замінити тільки непримітивний типів для параметрів типу K та V :
Зверніть увагу , що компілятор Java autoboxes 8 to Integer.valueOf(8) and 'a' to Character('a'):
Можна створити об'єкт параметра типу за допомогою відображення:
Можна викликати на append метод наступним чином :
Якщо статичні поля параметрів типу було дозволено, то наступний код буде:
Оскільки статичне поле os розділяє phone, pager, і pc , що є фактичний тип os? Це не може бути Smartphone, Pager, і TabletPC одночасно. Не можна створювати статичні поля параметрів типу.
Набір параметрезованих типів переданих в rtti метод:
Середовище виконання не відслідковує параметрів типу, тому він не може сказати різницю між ArrayList <Integer> і ArrayList <String> .
Найбільше, що можна зробити , це використати необмежений груповий символ , щоб переконатися , що список ArrayList :
Наступний код показує, що відбувається, коли різні типи вставляються в масив:
Якщо спробувати те ж саме з загального списку, не було б проблемою:
Якщо масиви параметрезованих списків були дозволені, попередній код не зможе кинути потрібний ArrayStoreException .
Не можна зловити екземпляр параметра типу:
Можна використовувати параметр типу в throws:
- Неможливо створити універсальних типів з примітивними типами
- Неможливо створити екземпляри типу параметрів
- Не можна оголошувати статичні поля, типи яких Тип Параметри
- Неможливо використовувати зліпки або InstanceOf З параметрезованих типів
- Неможливо створити масиву параметрезованих типів
- Неможливо створити, спіймати або відкидати об'єкти параметрезованих типів
- Не може перевантажити спосіб, де формальні типи параметрів кожної перевантаження Erase до того ж типу Raw
1. Неможливо створити Generic типів з примітивними типами
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
// ...
}
Pair<int, char> p = new Pair<>(8, 'a'); // compile-time error-Помилка часу компіляції
Pair<Integer, Character> p = new Pair<>(8, 'a');
Pair<Integer, Character> p = new Pair<>(Integer.valueOf(8), new Character('a'));
2. Неможливо створити екземпляри типу параметрів (Type Parameters)
Не можна створити екземпляр параметра типу. Наприклад, наступний код викликає помилку компіляції:public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
List<String> ls = new ArrayList<>(); append(ls, String.class);
3. Не можна оголошувати статичні поля, типи яких Type Parameters
Статичні поля параметрів типу не допускаються:public class MobileDevice<T> {
private static T os;
// ...
}
MobileDevice<Smartphone> phone = new MobileDevice<>(); MobileDevice<Pager> pager = new MobileDevice<>(); MobileDevice<TabletPC> pc = new MobileDevice<>();
4. Неможливо використовувати зліпки або InstanceOf з параметрезованих типів
Так як компілятор Java стирає всі параметри типу в родовому коді, ви не можете перевірити, який тип параметризований для універсального типу в даний час, використовується під час виконання:public static <E> void rtti(List<E> list) {
if (list instanceof ArrayList<Integer>) { // compile-time error
// ...
}
}
S = { ArrayList<Integer>, ArrayList<String> LinkedList<Character>, ... }
Найбільше, що можна зробити , це використати необмежений груповий символ , щоб переконатися , що список ArrayList :
public static void rtti(List<?> list) {
if (list instanceof ArrayList<?>) { // OK; instanceof requires a reifiable type
// ...
}
}
5. Неможливо створити масиву параметрезованих типів
Наприклад, наступний код не компілюється:List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error-Помилка часу компіляції
Object[] strings = new String[2]; strings[0] = "hi"; // OK strings[1] = 100; // An ArrayStoreException is thrown.
Object[] stringLists = new List<String>[]; //Помилка компілятора, але роблять вигляд, що це дозволено
stringLists[0] = new ArrayList<String>(); // OK
stringLists[1] = new ArrayList<Integer>(); //ArrayStoreException повинен бути викинутий,
// Але runtime не може його виявити.
6. Неможливо створити, спіймати або відкидати об'єкти параметрезованих типів
Загальний клас не може розширити Throwable клас прямо або побічно. Наприклад, такі класи не скомпілюються:// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ } // compile-time error
// Extends Throwable directly
class QueueFullException<T> extends Throwable { /* ... */ // compile-time error
public static <T extends Exception, J> void execute(List<J> jobs) {
try {
for (J job : jobs)
// ...
} catch (T e) { // compile-time error
// ...
}
}
class Parser<T extends Exception> {
public void parse(File file) throws T { // OK
// ...
}
}
7. Не можна перевантажити Method, де формальні типи параметрів кожної Overload Erase to the Same Raw Type
Клас не може мати два перевантажених методиpublic class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}