Сложный вопрос, на который я почти потерял всякую надежду. Я пытаюсь сделать
функция, но у меня проблемы с получением 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])
, но есть два добавленные трудности:
(T []) myObjectArray
выдает исключение ClassCastException
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 []
, даже если вам удастся создать его косвенно?