Есть ли какой-нибудь способ получить класс для Java или создать экземпляр типа с двойным родом?

Так сказать, у меня есть:

public class Foo<T> {
  // Some stuff
}

public interface Factory<T> {
  T newInstance();
  Class<T> getKlass();
}

И я хочу сделать реализацию Factory для сборки Foo:

public class FooFactory<T> implements Factor<Foo<T>> {
  private Class<Foo<T>> klass;
  public FooFactory(Class<Foo<T>> klass) {
    this.klass = klass;
  }

  public T newInstance() throws Exception {
    return klass.newInstance();
  }

  public Class<Foo<T>> getKlass() {
    return klass;
  }
}

Два вопроса:

  1. Могу ли я получить Класс>, если у меня есть только Класс? К сожалению, Foo является закрытым классом, и поэтому единственный код, который имеет всю картину (т.е. знает, что будет с T), не может знать о Foo и, следовательно, не может дать мне Class>.
  2. Есть ли лучший способ, которым я мог бы пойти об этом?

Спасибо!

PS Для тех, кто просит более подробно, здесь мы идем. Вся история в том, что Foo и FooFactory будут частными классами во внешнем классе. Foo широко используется во внешнем классе, и чтобы избежать ложной сборки мусора, я бы хотел использовать ObjectPool для создания экземпляров экземпляров Foo, а не обновлять их и постоянно собирать мусор. Однако, чтобы использовать мой ObjectPool, мне нужен Factory>, и внутри Outer я, очевидно, не могу знать, каким будет T, когда будет создан экземпляр Outer.

public class Outer<T> {
  private class Foo<T> { ... }
  private class FooFactory<T> {...}

  private ObjectPool<Foo<T>> fooPool;

  ...
}

2 ответа

Решение

Существуют способы создания информации о типе для Class<Foo<T>> но чтобы делать то, что вы хотите, вам просто нужно подавить все предупреждения FooFactory,

Во время выполнения Java использует Object во всех местах, где вы написали T, так что вы можете просто создать экземпляр Foo<Object> или же Foo.class, они одинаковые. Это называется стиранием типа.

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

Примечание. Если вы хотите сохранить информацию о типе, выполните ParameterizedType интерфейс

Есть только один Foo объект класса, который равен Foo.class, Хотя ты можешь написать Class<Foo<whatever>>это обманчиво, так как все равно Foo объект класса. Конечно нужно Class<Foo<T>> уметь звонить newInstance() и получить Foo<T>, Так что обойти тот факт, что вам нужно Class<Foo<T>> и это Foo.class имеет тип Class<Foo>Вы просто делаете кастинг:

public FooFactory() {
  this.klass = (Class<Foo<T>>)(Class<?>)Foo.class;
}

Обратите внимание, что нам не нужно Class<T> вообще, потому что вам не нужно знать T создать Foo<T>,

Другие вопросы по тегам