casting ArrayList.toArray() die ArrayList mit Generischen Arrays
Ist eine schwierige Frage, die ich bin nahe dran aufzugeben, alle Hoffnung auf. Ich versuche, mich ein
Funktion, aber ich habe Probleme bei der Anreise ArrayList.toArray()
Rückkehr der Typ den ich haben will.
Hier ist das minimal-Beispiel, das veranschaulicht mein problem:
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();
}
Normalerweise würde ich in der Lage sein, um das Formular zu verwenden (T[]) list.toArray(new T[0])
aber es gibt zwei zusätzliche Schwierigkeiten:
- Wegen der Kovarianz-Regeln, die ich nicht festgelegten arrays
(T[]) myObjectArray
gibt eineClassCastException
- Sie können nicht erstellen Sie eine neue Instanz eines generischen Typs, d.h. ich kann keine Instanz
new T[]
. Noch kann ich Klon auf eines der Elemente derArrayList
oder versuchen, sich in seine Klasse.
Ich habe versucht, einige Informationen über den folgenden Aufruf:
public static void main(String[] args) {
System.out.println(test("onestring", "twostrings"));
}
das Ergebnis ist von der form [Ljava.lang.Object;@3e25a5
was darauf hindeutet, dass der typecast auf die Rücksendung nicht wirksam. seltsamerweise sind die folgenden:
public static void main(String[] args) {
System.out.println(test("onestring", "twostrings").getClass());
}
kommt zurück mit:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at patchLinker.Utilities.main(Utilities.java:286)
Also meine beste Vermutung ist, dass es glaube ist es ein String-array label klug, aber intern ist ein Objekt-array, und alle versuche, access bringt, dass inconsistancy aus.
Wenn jemand finden können jede Art von arbeiten rund um das (da die beiden normalen workarounds sind mir verwehrt), wäre ich sehr dankbar.
K. Barad
JDK1.6
Bearbeiten
Danke an Peter Lawrey für die Lösung des ursprünglichen Problems. Nun die Frage ist, wie die Lösung für meine weniger triviales Beispiel:
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);
}
Das Ergebnis im moment ist
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)
Ich bin immer noch tun einige tests, um zu sehen, wenn ich mehr nützliche Informationen als das, aber im moment bin ich nicht sicher, wo zu beginnen. Ich werde alle weitere Informationen, die ich bekommen wie ich es bekommen.
K. Barad
edit 2
Einige Sie jetzt weitere Informationen an. Ich habe versucht, zu bauen das array manuell und übertragen Sie die Elemente in elementweise, so würde ich typecasting als T, sondern als T[]. Ich fand ein Interessantes Ergebnis:
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;
}
}
Ich bekomme immer noch folgende Ausgabe:
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)
Bedeutet dies, dass Sie nicht schreiben können, um ein T[]
selbst wenn es Ihnen gelingt zu erstellen eine indirekt?
- Ich schlage vor, kleben mit Sammlungen und verlassen hinter der alten Schule Referenz-arrays.
- Würde gerne, aber es gibt Zeiten, wenn Sie haben keine Wahl in der Angelegenheit. Rückwärts-Kompatibilität bedeutet immer, dass etwas rückständig.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem auf deinem zweiten code-Beispiel wird verursacht, weil Ihre
T[] typeVar
: Eingabe ist eine zwei-dim array, soinput[0]
zurück eine ein-dim-array (String [] statt String, wie erwartet).Wenn Ihr zum konvertieren Ihrer
List<T>
zu einemT[]
benötigen Sie einT typeVar
,Um es zu beheben:
Die resultierende Ausgabe:
if (input.length == 0)
fürif (input !=null && input.length == 0)
toArray() gibt immer ein array-Objekt.
Gibt ein array von einem bestimmten Typ, müssen Sie die Verwendung von toArray(Object[]).
Den richtigen Typ für das array-argument, müssen Sie die Verwendung der spezifischen Klasse oder in diesem Fall verwenden Sie Reflexionen.
versuchen
Können Sie nicht erstellen Sie ein array mit einem generischen Typ-parameter. Der einfache Grund dafür ist die Tatsache, dass java in der Regel löscht die generische Typ-Informationen zur Laufzeit, so dass die Laufzeitumgebung hat keine Ahnung, was T ist, (wenn T ist ein generischer Typ-parameter).
Also die Lösung ist, um tatsächlich Holen Sie sich ein halten Sie die Typ-Informationen zur Laufzeit. Dies erfolgt in der Regel durch die übergabe um eine
Class<T> type
parameter, aber in diesem Fall können Sie vermeiden, dass:@peter die Antwort sieht gut aus und ich würde es zu benutzen :).