приведение ArrayList.toArray () к ArrayList общих массивов

Сложный вопрос, на который я почти потерял всякую надежду. Я пытаюсь сделать функция, но у меня проблемы с получением ArrayList.toArray () для возврата нужного мне типа.

Вот минимальный пример, демонстрирующий мою проблему:

public static <T> T[] test(T one, T two) {
    java.util.List<T> list = new ArrayList<T>();
    list.add(one);
    list.add(two);
    return (T[]) list.toArray();
}

Обычно я мог бы использовать форму (T []) list.toArray (new T [0]) , но есть два добавленные трудности:

  1. Из-за правил ковариации я не могу выполнить приведение типов массивов, (T []) myObjectArray выдает исключение ClassCastException
  2. . Вы не можете создать новый экземпляр универсального типа, то есть я не может быть экземпляром new T [] . Я также не могу использовать clone для одного из элементов ArrayList или попытаться получить его класс.

Я пытался получить некоторую информацию, используя следующий вызов:

public static void main(String[] args) {
   System.out.println(test("onestring", "twostrings"));
}

результат: форма [Ljava.lang.Object; @ 3e25a5 , предполагая, что приведение типа в возврате неэффективно. как ни странно, следующее:

public static void main(String[] args) {
    System.out.println(test("onestring", "twostrings").getClass());
}

возвращается с:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at patchLinker.Utilities.main(Utilities.java:286)

Итак, я предполагаю, что он думает, что это метка массива String, но внутренне является массивом Object, и любые попытки доступа устраняют это несоответствие.

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

К.Барад JDK1.6


Править


Спасибо Питеру Лоури за решение начальной проблемы. Теперь проблема в том, как применить решение к моему менее тривиальному примеру:

public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;
    T[] typeVar;
    for (T[] subArray : input) {
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }
    if (input.length > 0) {
        typeVar = input[0];
    } else {
        return null;
    }
    return (T[]) outList.toArray((T[]) java.lang.reflect.Array.newInstance(typeVar.getClass(),outList.size()));
}

public static void main(String[] args) {
    String[][] lines = { { "111", "122", "133" }, { "211", "222", "233" } };
    unTreeArray(lines);
}

Результат на данный момент

Exception in thread "main" java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at java.util.ArrayList.toArray(Unknown Source)
at patchLinker.Utilities.unTreeArray(Utilities.java:159)
at patchLinker.Utilities.main(Utilities.java:301)

Я все еще провожу несколько тестов, чтобы увидеть, могу ли я получить более полезную информацию, чем эта, но на Сейчас я не уверен, с чего начать. Я добавлю любую информацию, которую получу, когда получу.

K.Barad


edit 2


Еще немного информации. Я попытался создать массив вручную и передать элементы поэлементно, поэтому я бы использовал тип T, а не T []. Я обнаружил интересный результат:

public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;
    T[] outArray;
    for (T[] subArray : input) {
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }
    if (outList.size() == 0) {
        return null;
    } else {
        outArray = input[0];// use as a class sampler
        outArray =
                (T[]) java.lang.reflect.Array.newInstance(outArray.getClass(), outList.size());
        for (int i = 0; i < outList.size(); i++) {
            System.out.println(i + "  " + outArray.length + "   " + outList.size() + "   "  + outList.get(i));
            outArray[i] = (T) outList.get(i);
        }
        System.out.println(outArray.length);
        return outArray;
    }
}

Я все еще получаю следующий результат:

0  6   6   111
Exception in thread "main" java.lang.ArrayStoreException: java.lang.String
at patchLinker.Utilities.unTreeArray(Utilities.java:291)
at patchLinker.Utilities.main(Utilities.java:307)

Означает ли это, что вы не можете писать на T [] , даже если вам удастся создать его косвенно?

9
задан xav 7 April 2014 в 10:52
поделиться