Callback vs. Reflection

Ich implementiere gerade mehrere Container für Elemente. Dabei hat sich herausgestellt, dass einige Funktionalität immer wieder vorkommt, weshalb nun eine abstrakte Klasse “AbstractContainer” implementiert wird.
In diesem Zusammenhang muss die neue abstrakte Klasse auch Arrays von ihren Elementen zurück geben. Da sie bereits in einem bestehenden Umfeld agieren, ist es nicht mehr möglich auf Collections zu wechseln.

Jetzt ist die Frage, wie diese Arrays am besten generiert werden. Im Moment sehe ich zwei Möglichkeiten und frage mich, welche die bessere ist:

Möglichkeit 1: Callback

   public E[] getAll(){
     E[] result = createArray(size());
     /* array füllen */
     return result;
   }
   
   protected abstract E[] createArray(int size); // Jeweilige Implementierung mit "return new Element[size];"
}```

Möglichkeit 2: 
```public abstract AbstractContainer<E> {
   private Class<E> type;

   public AbstractContainer(Class<E> type){this.type = type;}

   public E[] getAll(){
     E[] result = Array.newInstance(type, size());
     /* array füllen */
     return result;
   }```

Wie würdet ihr es umsetzen? Gibt es irgendwelche signifikanten Vor- oder Nachteile, wodurch eine der Lösungen klar zu prefferieren ist!?

Wenn dieses (für mich noch magische) “Array Füllen” in der Elternklasse auch erledigt werden kann, würde ich aus API-Sicht die Möglichkeit 2 empfehlen. Da wäre alles ausimplementiert und das bietet für Nutzer Deiner Klasse weniger Möglichkeiten, etwas falsch zu machen. Die Klasse Array liegt zwar im package reflect, wenn man den Sourcecode von Array.newInstance anschaut, sieht man aber, dass am Ende eine native-Methode aufgerufen wird. Ich würde mir da also auch keine Sorgen machen, was die Performance angeht.

Danke für die schnelle Antwort. Weitere Meinungen sind gerne erwünscht :wink:

Die Methode getAll ist auch fiktiv. Ich brauchte nur ein kleines Beispiel, um etwas Code zu posten. Und es geht ja auch nicht darum, wie ich generisch ein Array füllen kann, sondern wie es erstellt wird.

Das magische Array-Füllen verwundert mich auch etwas. Ist der konkrete Typ für die Oberklasse nicht notwendig zum Befüllen?

Füllst du das Ganze aus einer List? Falls ja, kannst du nicht #toArray benutzen?

Die Klasse zu übergeben ist zwar nicht wirklich hübsch, aber auch nicht sooo ungewöhnlich (wird z.B. bei EnumMap auch so gemacht) und immer noch viel bequemer, als in jeder Unterklasse eine Methode zum Array-Erzeugen schreiben zu müssen. Ich würde also auch Variante 2 bevorzugen.

Na so magisch ist es jetzt auch nicht. Die Elemente liegen eigentlich gar nicht im Container, sondern werden von diesem nur aus einer Datenquelle (Datenbank) geladen. Über eine Abstrakte Methode ( E toInstance(Object source) ) kann ich eine Instanz zu einem Element-Objekt umwandeln. Für den Fall, dass ich mehrere solcher Quell-Objekte habe, kann ich auch diese über die eine Methode „toInstance“ abfertigen, da ich sie ja nur für jedes Quell-Element einzeln aufrufen muss. Frage die bleibt: Wie komme ich an das Array, das ich zurückgeben muss. Darum dieser Thread.

[QUOTE=dev]Füllst du das Ganze aus einer List? Falls ja, kannst du nicht #toArray benutzen?[/QUOTE]Selbst wenn ich sie aus einer Liste laden würde, würde mich java.util.Collection.toArray() vor das selbe Problem stellen. :stuck_out_tongue_winking_eye:

EDIT: Ich denke, ich werde dann wirklich Version 2 nehmen. Danke für eure Antworten.

Okay, das seh ich ein :smiley: