Что означает универсальность класса Class <T>? Что такое Т? - PullRequest
39 голосов
/ 23 февраля 2012

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

Ответы [ 4 ]

48 голосов
/ 23 февраля 2012

Параметр типа <T> был добавлен к java.lang.Class, чтобы включить одну конкретную идиому 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 СОЛНЦЕ Oracle опубликовала хорошую статью, объясняющую все это .
2 Это отличается от реализаций обобщений без стирания типаНапример, один в .NET.
3 Учебник по Java Generics от Oracle.

8 голосов
/ 05 сентября 2012

Ответ от 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 сам по себе является аргументом универсального типа, то все эти приведения будут отменены, что приведет к последовательности предупреждений компилятора. Вы можете подавить их, но основная проблема остается: компилятор не может проверить достоверность этих приведений, если вы правильно не используете аргумент типа.

1 голос
/ 23 февраля 2012

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

0 голосов
/ 23 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...