2017-02-06 2 views
5

Мне нужно написать java-метод, который принимает класс (а не объект), а затем создает ArrayList с этим классом в качестве элемента каждого элемента массива. Пример псевдокода:Пропустить класс типа как параметр для использования в ArrayList?

public void insertData(String className, String fileName) { 
     ArrayList<className> newList = new ArrayList<className>(); 
} 

Как это сделать на Java?

+4

ли это быть 'Струнный className'? Было бы проще, если бы вы могли передать фактический объект класса, например 'insertData (ExampleClass.class, fileName)'. – nickb

+0

Я не знаю, какой класс я передаю. – Greymarch

ответ

4

Вы можете использовать Generic methods

public <T> void insertData(Class<T> clazz, String fileName) { 
    List<T> newList = new ArrayList<>(); 
} 

, но если вы должны использовать этот контракт insertData(String className, String fileName), вы не можете использовать дженерики, потому что тип элемента списка не может быть решена в компиляции с помощью Java.

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

public void insertData(String className, String fileName) { 
    List newList = new ArrayList(); 

    Class clazz; 
    try { 
     clazz = Class.forName(className); 
    } catch (ClassNotFoundException e) { 
     throw new RuntimeException(e); // provide proper handling of ClassNotFoundException 
    } 

    Object a1 = getSomeObjectFromSomewhere(); 

    if (clazz.isInstance(a1)) { 
     newList.add(a1); 
    } 
    // some additional code 
} 

но без информации о классе вы сможете использовать только потому, что вы Object не может передать ваш объект UnknownClass в ваш код.

+0

Обратите внимание, что это изменяет сигнатуру метода OP, которая может быть или не быть желательной. – nickb

+0

@nickb согласен, обновленный ответ –

+0

@ VladBochenin Не могли бы вы представить пример реализации вышеуказанного кода? – Greymarch

2

Влад Боченен дает хороший способ, но не имеет смысла предоставлять генератор T, который не имеет ничего общего с вашим методом.
Он ставит нулевые ограничения в код insertData(), который управляет списком.
Вы будете вынуждены сделать бросок в коде, и это победит цель Generics.

Я полагаю, вы хотите манипулировать некоторыми примерами известных классов в insertData().
И если вы используете общий в своем случае, было бы более значимым, если у вас есть подтипы классов для манипулирования.

Таким образом, у вас может быть метод, который принимает базовый тип и его подклассы.

public static <T extends YourClass> void insertData(Class<T> clazz, String fileName) { 
    List<T> newList = new ArrayList<>(); 
    T t = newList.get(0); 
    // here I can manipulate something that derives from YourClass 
} 
+0

@Downvoter Не могли бы вы объяснить? Как обычно, я полагаю, что нет. – davidxxx

+0

Я не являюсь нисходящим, но ваше утверждение о том, что «не имеет смысла предоставлять T-родовое, которое происходит из ничего в вашем методе», неверно.Конечно, вы не можете вызывать какие-либо методы в элементах списка из метода, если вы не прибегаете к отражению, но вы можете заполнить «Список » (возможно, значения десериализованы из файла с заданным именем). Обычно вы хотели бы вернуть этот список. В callsite вы знаете 'T' во время компиляции и можете вызывать любые методы, которые вам нравятся. – Hulk

+1

@Hulk В вопросе он не возвращает список. Если это так, то это будет иметь смысл. «вы можете заполнить список (возможно, с десериализацией значений из файла с заданным именем)». Это еще раз побеждает цель дженериков, поскольку вы помещаете экземпляры чего-то, извлеченного из файла в Список «Объект». Т происходит от ничего, следовательно, только от «Объекта». В чем преимущество Generics здесь? В этом случае мы могли бы упростить API для удаления параметра класса и добавить '@ SuppressWarnings' в метод insertData(), поскольку, наконец, Generics не несет никакой безопасности здесь. – davidxxx

0

Я думаю, что то, что вы действительно хотите сделать, это вернуть сгенерированный List. Это то, что это может выглядеть:

public <T> List<T> loadData(Class<T> clazz, String fileName) { 
    List<T> newList = new ArrayList<>(); 

    //...populate list somehow (e.g. with values deserialized from the file named "filename") 

    return newList; 
} 

Это, как он может быть использован:

List<String> names = loadData(String.class, "someFileContainingNameStrings"); 
List<Double> temperatures = loadData(Double.class, "someFileContainingTemperatureData"); 
Смежные вопросы