Подтвердить что ты не робот

Что означает общий характер класса Class <T>? Что такое T?

Я понимаю дженерики, когда дело доходит до коллекций. Но что это значит в случае класса Class<T>? Когда вы создаете экземпляр объекта Class, существует только один объект. Итак, почему параметр T? Что это такое? И почему это необходимо (если это так)?

4b9b3361

Ответ 1

Параметр <T> добавлен в java.lang.Class, чтобы включить один конкретный idiom 1 - использование объектов Class в качестве объектов объектов, защищенных типом. По существу, добавление <T> позволяет создавать экземпляры классов безопасным типом, например:

T instance = myClass.newInstance();

Параметр типа <T> представляет сам класс, позволяющий избежать неприятных эффектов стирания типа, сохраняя Class<T> в родовом классе или передавая его как параметр в общий метод. Обратите внимание, что T само по себе не будет достаточным для выполнения этой задачи 2: тип T стирается, поэтому он становится java.lang.Object под капотом.

Вот классический пример, когда параметр <T> класса становится важным. В приведенном ниже примере компилятор Java может обеспечить безопасность типа, позволяя вам создавать типизированную коллекцию из строки SQL и экземпляр Class<T>. Обратите внимание, что класс используется как factory и что безопасность его типа может быть проверена во время компиляции:

public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
    Collection<T> result = new ArrayList<T>();
    /* run sql query using jdbc */
    for ( /* iterate over jdbc results */ ) {
        T item = c.newInstance();
        /* use reflection and set all of item’s fields from sql results */
        result.add(item);
    }
    return result;
}

Так как Java стирает параметр типа, делая его java.lang.Object или класс, указанный в качестве общей верхней границы, важно иметь доступ к объекту Class<T> внутри метода select. Поскольку newInstance возвращает объект типа <T>, компилятор может выполнять проверку типов, исключая приведение.

<ч/" > 1 SUN Oracle опубликовала хорошую статью, объясняющую все это. 2 Это отличается от реализаций дженериков без стирания типа, например, в .NET.
3Учебник Java Generics от Oracle.

Ответ 2

ответ dasblinkenlight уже продемонстрировал одно из основных применений этого параметра. Есть еще один аспект, который я считаю уместным: используя этот параметр, вы можете ограничить класс, который хотите передать в определенном месте. Так, например,

Class<? extends Number> cls

означает, что cls может быть любым классом, реализующим интерфейс Number. Это может помочь поймать определенные ошибки во время компиляции и сделать требования аргументов класса более явными.

Возможно, сравнение с случаем без дженериков в порядке

// Java ≥5 with generics    // Java <5 style without generics
Class<? extends Foo> c;     Class c;
Foo t1 = c.newInstance();   Foo t1 = (Foo)c.newInstance();
Object obj;                 Object obj;
Foo t2 = c.cast(obj);       Foo t2 = (Foo)c.cast(obj);

Как вы можете видеть, не имея T в качестве аргумента, потребуется несколько явных приведений, так как соответствующие методы должны были бы возвращать Object вместо T. Если Foo сам является аргументом общего типа, тогда все эти отбрасывания будут сняты, что приведет к последовательности предупреждений компилятора. Вы можете их подавить, но основная проблема остается: компилятор не может проверить достоверность этих приводов, если вы не используете правильный аргумент типа.

Ответ 3

В Java есть один метакласс: Class. Его экземпляры (только один для каждого типа существует) используются для представления классов и интерфейсов, поэтому T in Class<T> относится к типу класса или интерфейса, который представляет текущий экземпляр Class.

Ответ 4

Использование дженериков в типе класса top определяет тип класса. Если у меня есть "класс obj", мой объект obj может содержать только детей Charsequence. Это необязательный аргумент. Я часто ставил '?' чтобы избежать предупреждений из Eclipse IDE, если мне не нужен определенный тип класса.