Generisch mehrdimensionale Arrays erzeugen?

dbzworld

Grünschnabel
Hallo,
ich arbeite momentan an einem Plugin(OSGi) Tracker welches Plugins die in einem Netzwerk oder einer OSGi Platform laufen aufspürt und alle Interfaces und deren angebotenen Methoden anzeigt.
Nun kann man als User so eine Methode anklicken und Rechts escheint daraufhin eine Tabelle, welches die Inputs anzeigt die die Methode in der Signatur hat.
Das funktioniert auch alles.
Es werden nur Methoden mit primitive Datentypen in der Signatur unterstützt, da sonst sonst die Eingabe von Input bei anderen Datentypen eher schwirig wird.
Naja soweit läuft alles. Nun sollte ich auch Mehrdimensionale Arrays hinzunehmen. Abfangen solcher Arrays klappt wunderbar. Nun der User baut sich dann je nach Dimension sein Array in einem JTree, im Anschluss hole ich alle Daten in den Blättern ab und packe sie z.B. eine ArrayList. Im nächsten Schritt müsste ich je nach Dimension des Arrays ein m.dim.Array aus den Daten bauen und diese der Methode zurückgeben, da es ja in der Signatur verlangt wird. Genau da ist mein Problem, die Anwendung soll generisch sein, sprich in der Signatur steht z.B.:
int[] [] [] zahlen
Meine Anwendung erkennt das Array in der Signatur korrekt mit drei Dimensionen und setzt die tiefe des vom User zu erzeugenden Baums dementsprechend fest.
Dabei kann der User aber unendliche viele Elternknoten und Datenknoten in der letzten Dimension erzeugen, da ja die Klammern in der Signatur nicht vorinitialisiert sind. Dabei hat der Baum in diesem Fall nur eine Tiefe von maximal drei.
Ich muss also nachdem ich die Daten in einen ArrayIist packe diese entsprechend der Struktur des Baumes, z.B.: 1 Großelternknoten dann 2 Elternknoten und schließlich je Elternknoten zwei Datenknoten,
wäre als Array: int[] [] [] zahlen = new int [1] [2] [2] .
Die Probleme sind also:
- das m.Dim.Array in der Signatur kann beliebig viele Dimensionen haben
- dabei ist das Array nicht initilisiert da ja in der Signatur (int zahlen [][][]...) steht
- somit kann man beliebig viele Elternknoten und Datenknoten erzeugen, wobei dies durch die Tiefe=Dimension beschränkt ist.
- Die Schwierigkeit ist, es lässt sich generisch kein m.Dim.Array erzeugen/initialisieren da ich ja die einzelnen Dimensionen nicht vorher weiß.

Man könnte höchstens mit switch arbeiten z.B.:
Pseudocode:

switch(dimension)
case 2:
int [][] a = new int[Elternknoten aus Baum][Datenknoten aus Baum]
case 3:
int [][][] a = new int[Elternknoten aus Baum][Elternknoten aus Baum][Datenknoten
aus Baum]
usw...


was aber nicht generisch wäre, ich muss ja m.Dim.Arrays mit beliebiger Dim. abfangen...
Habt ihr evtl. Lösungen wie man es implementieren könnte?
In meinen Augen, sehe ich kein Ausweg somit wäre die Unterstützung von m.Dim.Arrays nicht realisierbar da ich keine m.Dim.Arrays generisch erzeugen kann.
Evtl habe ich auch irgendwo einen Denkfehler...
Würde mich über Anregungen und Tipps freuen.
Vielen dank vorab.

gruß
dbzworld
 
Jede Klasse erbt von java.lang.Object die Methode getClass(). Die zurückgegebene Klasse kannst du verwenden, um mit der Methode newInstance der Klasse java.lang.reflect.Array ein Array für die gewünschte Klasse zu bekommen. Von diesem Array kannst du dann auf diese Weise wieder ein Array machen usw...
 
Hallo,

ich glaube du suchst das hier:
Java:
package de.tutorials;

import java.lang.reflect.Array;

public class GenericArrayCreation {
  public static void main(String[] args) {
    int[][][] a =(int[][][]) Array.newInstance(int.class, 1,2,2);
    System.out.println(a);
    a[0][1][1] = 1;
    System.out.println(a[0][1][1]);
  }

}

Gruß Tom
 
Vielleicht ist ihm diese Version lieber

Java:
import java.lang.reflect.Array;
 
public class GenericArrayCreation {
  public static void main(String[] args) {
    Class cls;
    int a = 4;
    Object b = Array.newInstance(a.getClass(), 7);
    Object c = Array.newInstance(b.getClass(), 9);
    cls = a.getClass(); System.out.println("Klasse a: "+cls.getName());
    cls = b.getClass(); System.out.println("Klasse b: "+cls.getName());
    cls = c.getClass(); System.out.println("Klasse c: "+cls.getName());
  }
}
 
Vielen dank erstmal an euch!

Hallo,

ich glaube du suchst das hier:
Java:
package de.tutorials;

import java.lang.reflect.Array;

public class GenericArrayCreation {
  public static void main(String[] args) {
    int[][][] a =(int[][][]) Array.newInstance(int.class, 1,2,2);
    System.out.println(a);
    a[0][1][1] = 1;
    System.out.println(a[0][1][1]);
  }

}

Gruß Tom

Das Problem dabei ist ich kann ja auch Arrays haben mit mehr als drei Dimensionen, generell unendlich hängt halt von dem Array in der Signatur ab.
So müsste ich alle Fälle abdecken, das wäre unmöglich bzw. zu aufwendig ok keiner wird jemals ein Array mit 100 Dimensionen in einer Signatur verlangen, aber so ist es leider gefordert.

Es wäre gut wenn man die Klammern des Arrays per String erzeugen kann was aber leider nicht möglich ist. Bei 3 Dimensionen z.B. würde eine Hilfsmethode getKlammern einen String s zurückliefern welches genau [][][] Klammern beinhalten würde
Also
int getKlammern() a =(getKlammern()) Array.newInstance(int.class, 1,2,2);

Diese newInstance Sache hatte ich mir schon vorher angeschaut, das hilft in diesem Fall leider nicht weiter, das Problem sind wirklich nur die Klammern. Die Menge der Klammern soll dynamisch/generisch erzeugt werden.
Ich hoffe ihr versteht was ich meine.

Vielleicht ist ihm diese Version lieber

Java:
import java.lang.reflect.Array;
 
public class GenericArrayCreation {
  public static void main(String[] args) {
    Class cls;
    int a = 4;
    Object b = Array.newInstance(a.getClass(), 7);
    Object c = Array.newInstance(b.getClass(), 9);
    cls = a.getClass(); System.out.println("Klasse a: "+cls.getName());
    cls = b.getClass(); System.out.println("Klasse b: "+cls.getName());
    cls = c.getClass(); System.out.println("Klasse c: "+cls.getName());
  }
}

Hier bekomme ich leider einen Fehler:
Cannot invoke getClass() on the primitive type int
Was passiert dei dem Code generell?
Erzeugst du ein Array welches so aussieht: int[][][] c = new int [9][7][4] ?
Oder was ganz anderes?
EDIT:
Habe es mit Integer a = new Integer(4); gelöst als Output bekomme ich :

Klasse a: java.lang.Integer
Klasse b: [Ljava.lang.Integer;
Klasse c: [[Ljava.lang.Integer;

Inwiefern hilft mir das weiter?
 
Zuletzt bearbeitet:
Hallo,

Mit den Methoden aus java.lang.reflect.Array kannst du genau das machen was du willst... denn damit kannst du Arrays mit beliebig vielen Dimensionen erzeugen und auf die entsprechenden Elemente unterhalb bestimmter Dimensionen zugreifen.

Im unteren Beispiel sage ich mit dem (potentiell dynamischen) erzeugten dimensions -Array, dass ich ein Array mit 4 Dimensionen erzeugen will, wobei die erste 1, die zeite 2, die dritte 3 und die vierte Dimension 4 Elemente hat.

Hier könnte ich nun beliebig weiter machen...

Java:
package de.tutorials;

import java.lang.reflect.Array;

public class GenericArrayCreation {
  public static void main(String[] args) {
    int[] dimensions = { 1, 2, 3, 4 };
    Object array = Array.newInstance(int.class, dimensions);
    System.out.println(array);

    //dynamisch
    set(array, 4711,0,1,2,3);
    System.out.println(get(array, 0,1,2,3));
    
    //statisch
    int[][][][] x  = (int[][][][])array;
    x[0][1][2][2] = 12345;
    System.out.println(x[0][1][2][2]);
    
  }


  private static void set(Object array, Object value, int... dimensionIndices) {
    Object dimensionArray = getNestedArray(array, dimensionIndices);
    int lastIndex = Math.max(0, dimensionIndices.length - 1);
    Array.set(dimensionArray, dimensionIndices[lastIndex], value);
  }


  private static Object get(Object array, int... dimensionIndices) {
    Object dimensionArray = getNestedArray(array, dimensionIndices);
    int lastIndex = Math.max(0, dimensionIndices.length - 1);
    Object result = Array.get(dimensionArray, lastIndex);
    return result;
  }


  private static Object getNestedArray(Object array, int... dimensionIndices) {
    Object dimensionArray = array;
    for (int i = 0; i < dimensionIndices.length - 1; i++) {
      dimensionArray = Array.get(dimensionArray, 0);
    }
    return dimensionArray;
  }
}

Ausgabe:
Code:
[[[[I@3e25a5
4711
12345

Gruß Tom
 
Was passiert dei dem Code generell?
Erzeugst du ein Array welches so aussieht: int[][][] c = new int [9][7][4] ?
Oder was ganz anderes?

Inwiefern hilft mir das weiter?

Genau das. Auf diese Weise kannst du Array von einer Klasse erzeugen, wo du nicht genau zu wissen brauchst, welche genau das ist, du kannst es also z.B. in einer rekursiven Funktion verwenden, die dann für den Aufbau des Arrays und sein Befüllen mit Daten sorgt, denn während des Einlesens von Daten weißt du eventuell noch nicht genau, wieviele Dimensionen du brauchst, beispielsweise beim Aufbau und/oder Traversieren einer Baumstruktur. Aber der Ansatz von Thomas funktioniert auch gut.
 
Zurück