Обобщения Java-отражений - передаются путем передачи параметра во время компиляции? - PullRequest
1 голос
/ 04 июля 2011

Существует следующая ситуация:
Дан класс с общим полем в нем.Можно ли создать экземпляр поля во время выполнения с экземпляром T?

class Root<T>{
   T var;

   Root(){
     //instantiate var with an instance of T here
   }
}

Ответы [ 5 ]

4 голосов
/ 04 июля 2011

Если у вас есть класс, который расширяет Root<T> и устанавливает параметр типа в его предложении extends, то его можно выкопать с помощью getGenericSuperclass () . Например, Guice использует этот подход для предоставления информации о параметрах типа введенным классам.

В противном случае лучше всего передать экземпляр Class<T> в качестве параметра конструктора и использовать его. Это также приведет к более простому коду, хотя немного больше шаблонного для каждого экземпляра класса.

2 голосов
/ 04 июля 2011

Нет.

Java использует стирание типа , поэтому универсальный параметр не существует во время выполнения.

1 голос
/ 04 июля 2011

Нет способа узнать тип T во время выполнения, поскольку он стирается во время компиляции.

Однако вы можете добавить новый параметр в конструктор типа Class<T>.Компилятор будет гарантировать, что переданный объект является экземпляром Class, соответствующим типу T, который вы указали для своего экземпляра Root.В вашем конструкторе вы можете затем использовать отражение для создания нового экземпляра T:

class Root<T> {

    T var;

    public Root(Class<T> klass) {
        var = klass.newInstance();
    }

}

Это предполагает, что ваш тип T имеет конструктор по умолчанию.

1 голос
/ 04 июля 2011

Если вам не дали экземпляр T во время выполнения, ответ - нет из-за стирания типа java . Во время выполнения T фактически заменяется на Object, поэтому необходимой информации не существует. По этой причине такие функции, как List.toArray, требуют, чтобы вы передавали типизированный массив для получения типизированного результата.

0 голосов
/ 04 июля 2011

Нет. Если вам действительно нужна эта функциональность, вам нужно будет передать тип в вашем конструкторе.

Как это:

class Root<T> {
  private T var;

  public Root(Class<T> type) {
    var = type.newInstance();
  }
}

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

...