Как я могу вызвать JUnit Parametrized runner для коллекции универсальных типов? - PullRequest
0 голосов
/ 22 ноября 2010

Итак, я пытаюсь вызвать тестер JUnit Parameterized для загрузки отдельных типов объектов общего назначения. Конкретные классы, которые будут использоваться, известны классам-потомкам.

Изначально мне удалось получить метод, который возвращает Collection<T> для работы с JUnit, но затем я понял, что JUnit действительно требует Collection<T[]> - у меня возникают проблемы при создании этого массива из-за нежелания / отказа Java создавать массивы дженериков.

protected static <T> Collection<T> someMethod(Class<T> someClass)
{
    Collection<T> result = new ArrayList<T>();
    T someBean;
    while (someCondition(...))
    {
        //Do some stuff to compute someBean

        result.add(someBean);
    }
    return result;
}

Теперь JUnit требует Collection<T[]>, например:

// (descendant class)
@Parameters
public static Collection<SomeActualClass[]> data()
{
    return someMethod(SomeActualClass.class);
}

Итак, я хочу изменить тип возвращаемого значения, выполнив что-то вроде:

protected static <T> Collection<T[]> someMethod(Class<T> someClass)
{
    Collection<T[]> result = new ArrayList<T>();
    T someBean;
    while (someCondition(...))
    {
        //Do some stuff to compute someBean

        result.add(new T[]{someBean});
    }
    return result;
}

К сожалению, Java не позволит мне сделать это, потому что вы не можете создавать универсальные массивы.

У меня возникает соблазн поставить заявление как result.add((T[])new Object[]{someBean}); но безопасно ли это? или есть лучший способ?

Ответы [ 2 ]

0 голосов
/ 06 января 2011

Это чертовски неловко, но должно работать следующее:

T[] theArray = (T[]) Array.newInstance(someClass, 1);
theArray[0] = someBean;

Ср.:

public class Foo<T> {

    final T t0;
    final T t1;
    final Class theClass;

    public Foo(T t0, T t1, Class<T> theClass) {
        this.t0 = t0;
        this.t1 = t1;
        this.theClass = theClass;
    }

    @SuppressWarnings("unchecked")
    public T[] getStuffArray() {
        T[] theArray = (T[]) Array.newInstance(theClass, 2);
        System.out.println(theArray.getClass().getName());
        theArray[0] = t0;
        theArray[1] = t1;
        return theArray;
    }

    public static void main(String[] args) {

        Number[] stuffArray = new Foo<Number>(1, 2.5, Number.class).getStuffArray();
        for (Number s: stuffArray) {
            System.out.println(s);
        }
    }
}

Если вы действительно уверены, , что этобезопасно, вы можете пропустить someClass и просто использовать someObject.getClass(), но тогда вы рискуете, что someObject является подклассом T, а не T, что в вышеприведенном случае даст вам ArrayStoreException пытаясь поместить 2.5 в Integer[].

(Обратите внимание, что если вы пройдете мимо этого - если вы сохраните только Integers - java позволит вам сойти с чтения этого Integer[] к Number[]. Не спрашивайте меня, почему.)

0 голосов
/ 22 ноября 2010

Вы можете попробовать использовать List<T>, а затем использовать метод toArray(T[]), и вы получите T[].

Вы также можете создать общий список только с одним элементом, используя Collections.singletonList(T o)

...