Обмеження на 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) { } }