Как избежать стирания типа Java - PullRequest
9 голосов
/ 10 декабря 2011

Есть ли способ избежать стирания типа и получить доступ к параметру типа?

public class Foo<T extends Enum<?> & Bar> {
    public Foo() {
        // access the template class here?
        // i.e. :
        baz(T.class); // obviously doesn't work
    }

    private void baz(Class<T> qux) { 
        // do stuff like
        T[] constants = qux.getEnumConstants();
        ...
    } 
}

Мне нужно знать о T и что-то с этим делать.Возможно ли это, и если да, то как это можно сделать без передачи в классе в конструкторе или где-либо еще, кроме параметра?

РЕДАКТИРОВАТЬ: Основная цельв этом вопросе стоит выяснить, существует ли какой-либо практический способ вокруг стирания типа.

Ответы [ 5 ]

5 голосов
/ 11 декабря 2011

На самом деле, нет практического способа удаления типа, потому что вы не можете запросить что-то, к чему у среды выполнения нет доступа. Предполагая, конечно, что вы согласны с тем, что подклассификация универсальных классов для каждого перечисления, которое реализует интерфейс Bar, является практическим решением.

enum Test implements Bar {
    ONE, TWO
}

class Foo<T> extends FooAbstract<Test> {
    public Foo() {
        ParameterizedType genericSuperclass =
                (ParameterizedType) getClass().getGenericSuperclass();
        baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]);
    }

    private void baz(Class<T> qux) {
        T[] constants = qux.getEnumConstants();
        System.out.println(Arrays.toString(constants)); // print [ONE, TWO]
    }
}

interface Bar {
}

class FooAbstract<T extends Enum<?> & Bar> {
}
2 голосов
/ 10 декабря 2011

Если вы хотите / можете передать токен класса конструктору:

public Foo(Class<T> clazz) {
    baz(clazz);
}

private void baz(Class<T> qux) {
    // ...
}

Таким образом, вы можете создавать объекты типа T с помощью Class.newInstance (), пытаясь привести произвольные объектыT с использованием Class.cast () и т. д.

Что вы собираетесь делать в baz ()?

1 голос
/ 11 декабря 2011

Используйте токен супертипа, предложенный Нилом Гафтером и используемый библиотеками, такими как guice, для этой цели.

См. http://gafter.blogspot.com/2006/12/super-type-tokens.html для исходного описания, и я проверил источник подсказок для рабочей реализации CA radio life.

есть другой q, у которого есть ответ с работающим примеромвстроенный здесь Как я могу передать класс в качестве параметра и вернуть универсальную коллекцию в Java?

1 голос
/ 10 декабря 2011

Как отметил Фолсер в своем ответе, единственный способ достичь этого - передать объект Class, представляющий тип T. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

100 * * * * * * * * * * * * * * * * * * * * * * * * *1007* * * * * * * * * * * * * * * * * * * * * * * * *

Вы, кажется, противостоите передаче объекта Class, но это единственный способ использовать метод getEnumConstants(). Вот отдельный пример:

public class Foo<T extends Enum<?> & Bar> {

   final Class<T> clazz;

   public Foo(Class<T> clazz) {

      this.clazz = clazz;
   }

   public void baz() {

      T[] constants = clazz.getEnumConstants();

      System.out.println(Arrays.toString(constants));
   }

   public static void main(String[] args) {

       new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]"
   }
}

public interface Bar { }

public enum MyEnum implements Bar { A, B, C, D; }
0 голосов
/ 07 апреля 2016

В некоторых случаях вы можете использовать обходной путь, предложенный Ричардом Гомесом. При создании экземпляров анонимных классов доступна информация о классе параметра типа.

class A<T>
{
    A()
    {
        java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType)  (this.getClass().getGenericSuperclass());
        System.out.println(parameterizedType.getActualTypeArguments()[0]);
    }
}

public class Example {
 public static void main(String[] args) {
     A<String> anonymous = new A<String>() {};  // prints java.lang.String
}
}

Обратите внимание, что несколько созданных таким образом экземпляров будут иметь разные анонимные классы, и если это проблема, вы можете захотеть использовать класс A_String_Factory с функцией createNew (), основанной на clone, чтобы заменить вызовы новыми.

...