Как я могу передать универсальный класс для метода в Java? - PullRequest
9 голосов
/ 16 апреля 2011

Предположим, у нас есть функция, которая создает объекты определенного класса:

public static <T> T createObject(Class<T> generic) {
    try {
        return generic.newInstance();
    } catch (Exception ex) {
        return null;
    }
}

Мы можем легко использовать функцию для создания экземпляров неуниверсальных типов.

public static void main(String[] args) {
    Foo x = createObject(Foo.class);
}

Можно ли сделать то же самое с универсальным типом?

public static void main(String[] args) {
    ArrayList<Foo> x = createObject(ArrayList<Foo>.class); // compiler error
}

Ответы [ 3 ]

8 голосов
/ 16 апреля 2011

Обобщения в Java реализуются посредством стирания типа.

Это означает, что ArrayList<T> во время выполнения является ArrayList.Компилятор просто вставляет преобразования для вас.

Вы можете проверить это с помощью следующего:

ArrayList<Integer> first = new ArrayList<Integer>();
ArrayList<Float> second = new ArrayList<Float>();

if(first.getClass() == second.getClass())
{
    // should step in the if
}
1 голос
/ 16 апреля 2011

Кроме того, если вы уверены в том, что делаете, и до тех пор, пока вы уверены, что ваш код не может вызвать загрязнение кучи, вы можете отключить предупреждение.

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

@SuppressWarnings("unchecked")
public static <T> T[] createArray(Class<T> anyClass, int size){
    T[]result = null;
    try{
        result = (T[]) Array.newInstance(anyClass, size);
    }catch(Exception e){
        e.printStackTrace();
    }
    return result;
}

Вот как я это использовал:

public static void main(String[] args) throws Exception{
    @SuppressWarnings("unchecked")
    List<String> jediNames = (List<String>) createObject(ArrayList.class);
    jediNames.add("Obiwan");

    String[] moreJedis = createArray(String.class, 10);
    System.out.println(moreJedis.length);
    moreJedis[0] = "Anakin";
}
0 голосов
/ 16 апреля 2011

Если вам действительно нужно, вы можете заставить его скомпилироваться без ошибок или предупреждений:

@SuppressWarnings("unchecked")
ArrayList<Foo> x = (ArrayList<Foo>) createObject(ArrayList.class);

Единственная проблема в том, что во время компиляции он не может гарантировать, что createObject() не добавляет в ваш ArrayList объекты, не относящиеся к типу Foo. Это, вероятно, безопасно в вашем случае, поэтому вы все равно получите выгоду от дженериков, не прибегая к использованию ArrayList<?>.

...