[Generics] Typparameter-Arrays



  • Hallo,

    ich wurde heute mit einer Frage konfrotiert, bei der es um Typparameter-Arrays bei generischen Typen ging.

    Angenommen, ich habe eine Klasse

    public class Example<T>
    

    welche den Typparameter T besitzt. Jetzt möchte ich in Example ein Array von T s erzeugen. Das würde man wohl ganz intuitiv beispielsweise mit

    T[] arr = new T[100];
    

    versuchen. Das geht aber nicht.

    Bei meiner Suche nach einer Lösung bin ich auch zwei mögliche Wege gestoßen:
    1. Man erzeugt ein Array von Object s und casted entsprechend nach T[] . Das ist aber a) nicht schön und b) birgt an manchen Stellen wohl auch Stolpersteine.
    2. Man nutzt Reflection und erzeugt über

    Array.newInstance(.., 100)
    

    ein neues Array. Das Problem: Der erste Parameter erwartet den "Typen des Arrays". Leider geht T.class nicht, weswegen man sich den Typen anderweitig besorgen muss. Für meinen konkreten Fall sähe das in etwa so aus:

    import java.lang.reflect.Array;
    
    public class Example<T> {
      public Example(Class<T> clazz, int size, ...) {
        T[] arr = Array.newInstance(clazz, size);
        // ...
      }
    }
    
    // irgendwo anders
    Example<Integer> ex = new Example<Integer>(Integer.class, 100);
    

    Das finde ich persönlich aber äußerst hässlich, weil ich eben gezwungen bin, den Typen des Typargumentes (heißt das so?) irgendwann konkret als Konstruktorargument anzugeben.

    Gibt es da irgendwelche schlauen Tricks, die das Ganze evtl. eleganter angehen? Die Möglichkeit der Nutzung von anderen Collections ist nicht gegeben, es geht hier wirklich nur um Arrays. Ist ja auch vielleicht von theoretischem Interesse, warum der naive Weg nicht funktioniert / funktionieren kann.



  • Collections sind die Lösung 😉

    Falls es denn unbedingt ein Array sein muss schau mal hier: http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation

    MfG SideWinder



  • SideWinder schrieb:

    Falls es denn unbedingt ein Array sein muss schau mal hier: http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation

    Ich habe mich in den vergangenen 3 Monaten recht intensiv mit diesen Themen auseinandersetzen müssen. Fazit: Fang gar nicht erst damit an. Mit C# bekommt man fast alles irgendwie hin, aber mit Java schreibst du für spezielle Generic-Anwendungen (eigentlich sollte ein Array von Typparameter-Instanzen ja nichts spezielles sein...) in der Regel mehr Code als wenn du auf die Generics verzichtest. Und schneller bist du bei Verzicht auch noch 😮



  • Hallo,

    ich bin selbst auch kein Fan von Java, bin aber durch die Uni gezwungen, mich damit zu beschäftigen. Da das mit Generics und Arrays wohl so kompliziert ist, würde ich sicherlich auch zu Collections tendieren, leider ist das Ganze aber eine Übungsaufgabe, bei der ein flexibles Array implementiert werden soll und Collections wurden noch nicht behandelt.



  • Knecht Purpecht schrieb:

    ich bin selbst auch kein Fan von Java, bin aber durch die Uni gezwungen, mich damit zu beschäftigen.

    Ich kenne das leider nur zu gut. Im Studium muss man leider einen ganzen Haufen UML- und Java-Propheten zufrieden stellen. Alternativen sind noch immer tabu.

    Zurück zu deinem Problem: Das Fundament von Java ist in seinen Grundzügen bald einmal 20 Jahre alt und hat riesige Veränderungen durchgemacht. Um die Kompatibilität zu wahren hat man sich leider dazu entschieden, die neuen Features der Sprache von den verwendeten JVMs zu entkoppeln. Das Resultat ist im konkreten Fall, dass Java als Sprache zwar Generics kennt, die JVMs als Runtime hingegen nicht.

    Der Compiler ist daher gezwungen, Type Erasure zu betreiben. Dabei werden sämtliche Informationen zur Verwendung von Generics entfernt, um ein Programm auf einer JVM überhaupt lauffähig zum machen. Den Typparameter T gibt es in der Realität gar nicht; es handelt sich ausschliesslich um syntactic sugar, damit man nicht ständig casten muss. Daher sind Example<Integer> und Example<String> für die JVM derselbe Typ Example (ohne Generics!).

    Als Konsequenz dieser ganzen Würgerei kannst du nicht einfach T[] instanzieren. Es geht nicht, weil es diesen Typen zur Laufzeit niemals geben kann.



  • Knecht Purpecht schrieb:

    Hallo,

    ich bin selbst auch kein Fan von Java, bin aber durch die Uni gezwungen, mich damit zu beschäftigen. Da das mit Generics und Arrays wohl so kompliziert ist, würde ich sicherlich auch zu Collections tendieren, leider ist das Ganze aber eine Übungsaufgabe, bei der ein flexibles Array implementiert werden soll und Collections wurden noch nicht behandelt.

    Mach einfach eine verkettete Liste und pack da eine generische Objektvariable rein.


Anmelden zum Antworten