2013-07-19 9 views
8

Ich bemerkte, dass in Java Array.newInstance()Object zurückgibt, anstatt T[]. Es ist verständlich, dass diese Methode eingeführt wurde, bevor Java generische Typen unterstützt.Gibt es eine generische Version von Array.newInstance?

Es ist jedoch eine Überraschung, dass es keine entsprechende generische Version von diesem gibt. Java 7's Arrays.copyOf ist nicht das gleiche - es kopiert den Inhalt des Parameters, anstatt ein neues Dummy-Array (mit allen Null-Objekten innerhalb) zu erstellen.

Da die Implementierung von diesem scheint trivial, gibt es keinen Grund, es nicht in die JRE hinzufügen? oder ich kann einfach keinen finden?

UPDATE

Es scheint, werde ich meine eigene "trivial" Umsetzung misunderstand die Frage zu stoppen bieten.

Ich poste diesen Code nicht als Antwort, weil es nicht die Antwort der Frage ist. Die Frage bezieht sich auf den Grund und/oder den vorhandenen Code, nicht auf die Implementierung.

UPDATE

Ich habe den Code aktualisiert, um es zu Arrays.copyOf ähnlich zu machen, und der Vorteil ist, kann der Programmierer einfach den Typ des Parameters ändern Sie den Code für eine andere Art einzustellen. Außerdem habe ich die Verwendung von Array.newInstance für primitive Typen eliminiert.

+0

Nein, es ist unmöglich, dies kompilierungssicher zu implementieren. Zum Beispiel können Sie keine neue Instanz von a erstellen: 'List []'. Der Compiler wird nie wissen, was der Typ von "T" ist und kann daher nicht garantieren, dass der Client-Code sicher ist. – Muel

+0

Da 'Arrays.copyOf' die Aufgabe erledigen kann, gibt es keinen offensichtlichen Grund, den Sie nicht haben können. –

+2

'Arrays.copyOf' bestimmt den konkreten Typ aus dem zu kopierenden Array. – pstanton

Antwort

7

Guava bietet just such a function. Es ist nicht das erste Mal, dass Guava (oder Apache Commons) einen häufig verwendeten Helfer zur Verfügung stellt, den das JDK aus irgendeinem Grund nicht hat.

Sie können dies wissen, aber einige Hintergrund für den Googler, der in Zukunft darüber stolpert: Der Grund, warum die Signatur nicht generisch gemacht werden kann, ist die Methode Array.newInstancereturned Object in Java 1.4, so für die Abwärtskompatibilität, die rohe Version des Methode sollte auch Object zurückgeben. Wenn es als generified worden war:

<T> T[] newInstance(Class<T> componentType, int length) 

... dann wäre der Rückgabetyp Object[], nicht Object. Dies würde die Rückwärtskompatibilität brechen, die die Java-Designer immer sehr bemüht haben.

Die Methoden Arrays.copyOf kamen nur mit Java 1.6, und mussten sich daher keine Gedanken über die Rückwärtskompatibilität machen.

+0

Jetzt verstehe ich, warum es nicht viel Sinn macht, dass 'newArray' primitive Typen unterstützt. Wenn Sie ein neues Array mit Typen erstellen möchten, die keine generischen Typparameter sind, können Sie einfach 'new XYZ []' verwenden. Wenn dies nicht der Fall ist, müssen Sie den Klassentyp verwenden, und nur in diesem Fall ist die Funktion "newArray" nützlich. –

+0

Sie müssen immer noch den Typ als Parameter übergeben ... – pstanton

+0

Es sollte kein Problem sein, wenn Sie ein ähnliches Parameter/Feld in Ihrer Methodensignatur/Klassendefinition benötigen. –

4

Nein, Sie müssen den konkreten Typ als Parameter auf die eine oder andere Weise übergeben. Wie Sie erwähnt haben, zeigt Arrays.copyOf dies in Aktion.

Class<T> type = determinteTheTypeSomehow(); 
return (T[]) Array.newInstance(type, length); 
+0

'Array.newInstance' erfordert eine' Klasse ', da' Arrays.copyOf' 'T []' erfordert, also erfordern sie einen zusätzlichen Parameter anstelle eines Typparameters. Ich frage mich nur, warum wir keine 'Arrays.newInstance' haben können, die' Class 'oder' T [] 'akzeptiert (nur als Vorlage; der Inhalt wird ignoriert). –

+0

Ja ich verstehe, aber Sie versuchen, die API zu Ihren Bedürfnissen zu biegen, die nie funktionieren wird;) Ich gebe zu, das kann frustrierend sein, aber das ist so wie es ist. – pstanton

+0

Wenn ich generische Typen schreibe, übergebe ich oft den konkreten Parametertyp als Argument für diesen (und andere) Zwecke an den Konstruktor. – pstanton

3

Der Grund, warum Array.newInstance() nicht wie <T> T[] newInstance(Class<T> class, int size) deklariert werden kann, ist, weil es verwendet werden kann, um Arrays von Primitiven zu erstellen. Wenn Sie zum Beispiel int.class mit dem Typ Class<Integer> übergeben, würden Sie von der Deklaration erwarten, dass sie ein Objekt Integer[] zurückgibt. Die Funktion gibt jedoch tatsächlich ein int[] Objekt zurück, das kein Untertyp von Integer[] ist, also hat es den falschen Typ.

Sicher, sie konnte eine zusätzliche Methode, wie newReferenceArrayInstance() hinzufügen, die vom Urtyp verbietet (z wirft eine Ausnahme, wenn eine primitive Art bestanden) und kann somit sicher zurückkehren T[] deklariert werden. Dies scheint jedoch so zu sein, als würde man eine völlig redundante Methode nur hinzufügen, um eine unkontrollierte Umwandlung zu vermeiden.

Verwandte Themen