Как создать другой список в Java, если указан список, но с другим классом в списке - PullRequest
0 голосов
/ 07 февраля 2012

У меня есть список, и мне нужно вернуть тот же тип списка.

Если это уместно, в моем случае Y - это интерфейс, а интерфейс X - его суперинтерфейс.

Iпредположим, что мне нужно использовать newInstance для получения типа List.

public List<Y> foo() {
    List<X> xList = -a method that returns List<X>-;
    List<Y> yList = xList.getClass().newInstance(); //Is this right?

    ...

    return yList;
}

Я мог бы просто создать ArrayList, но я не знаю, лучше ли это делать, так как я мог получить любой типсписок.

Ответы [ 4 ]

1 голос
/ 07 февраля 2012

Вы смешиваете класс List с его универсальным типом?Редко возникает необходимость возвращать конкретную реализацию List (например, если она должна быть сериализуемой).Я рекомендую просто использовать ArrayList, с соответствующим размером заранее.

Что касается интерфейсов, будьте осторожны, потому что, если Y расширяет X, вы вообще не можете помещать объекты из xList вyList (я полагаю, вы хотите), потому что в списке может быть экземпляр X, который не является Y.

0 голосов
/ 07 февраля 2012

Поскольку вы не знаете тип списка, вы также не знаете, есть ли у него открытый конструктор без аргументов, поэтому вы не можете быть уверены, что newInstance () не сгенерирует исключение.

Если вам не нужна копия списка, и вы знаете, что список содержит Y экземпляров, вы можете просто сделать

List<Y> yList = (List) xList;
0 голосов
/ 07 февраля 2012
List<Y> yList = (List<Y>) xList.getClass().newInstance();

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

final Constructor cons = xList.getClass().getDeclaredConstructor();
cons.setAccessible(true);
List<Y> yList = (List<Y>) cons.newInstance();

Если для класса нет доступного конструктора без аргументов, то вам, вероятно, не повезло! Для реализации классов рекомендуется предоставить конструктор вида:

public MyListClass(Collection<T> items)

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

0 голосов
/ 07 февраля 2012

Java реализует обобщения через стирание, поэтому во время выполнения вы не увидите никакой разницы между .getClass() для List<X> и List<Y>.Однако вы можете просто сказать:

List<Y> yList = new ArrayList<Y>(); // Or LinkedList, or whatever implementation you want.

Если вы не знаете, какую реализацию List использовать, и это то, что вы хотите получить, зависит от типа списка, поддерживающего xList, вы можетепо-прежнему используйте newInstance: вам просто нужно разыграть его:

List<Y> yList = (List<Y>)xList.getClass().newInstance();

Во время выполнения все, что у вас будет, это LinkedList или ArrayList или что-то подобное, но пока вы этого не сделаетеЧтобы добавить в список любые не-Y элементы, вы должны спокойно вернуть его как List<Y>.

...