Object von generischem Typ erzeugen

Hey,

ich hab eine Aufgabe, bei der eine Klasse “Factory” beliebig viele Objekte eines bestimmten Typen erzeugen können soll. Einzige Voraussetzung ist, dass dieser Typ das Interface “IPrototype” implementiert.
Dazu soll das Interface auch generisch sein, damit man man nur Objekte “erzeugen” kann, die das Interface implementieren und nicht sowas geht wie "IPrototype oder Ähnliches.

Das Interface hatte ich mir dann so gedacht:


}

Folgende 2 Klassen implementieren das Interface:

	
}
	
}```

Jetzt bin ich mir beim Interface schon unsicher. Der generische Typ soll ja selbst das Interface erweitern, und deswegen muss ich ja wieder E extends IPrototype<...> schreiben. Aber fragt sich ob ich für das ... dann wieder E nehme oder doch eine Wildcard? Dieses ineinander verschachtelte macht es mir wirklich sehr schwer. 

Dann gibt es die Factory bei der man eine bestimmte Anzahl an Objekten erzeugen soll: 
```public class Factory {

	public <T extends IPrototype<T>> List<T> create(IPrototype<T> prototype, int n) throws Exception {
		ArrayList<T> list = new ArrayList<T>();
		for (int j = 0; j < n; j++)
			list.add(...);
		return list;
	}
}```

Und hier bin ich mir nicht sicher, wie es gehen soll. 
Zuerst einmal. Macht es überhaupt Sinn als Übergabeparameter "IPrototype<T> zu nehmen, wenn man schon spezifiziert hat, dass T das Interface implementieren muss? Oder sollte man als Parameter dann einfach nur "T" nehmen? 

Das erzeugen dieses Objekts macht mir dann auch Probleme.
Hätte gedacht es geht irgendwie so: 

public <T extends IPrototype> T create(T prototype) throws Exception {
Class type = prototype.getClass();
return type.newInstance();
}

Allerdings möchte er dann immer, dass ich "prototype.getClass()" nach "T" caste, aber genau deswegen will ich ja eigentlich Generics nutzen. Damit ich nicht casten muss. 

Ich vermute das passt alles nicht so ganz zusammen, ich tuhe mich wirklich schwer mit Generics. Vor allem dadurch, dass das mit dem Interface implementieren praktisch immer doppelt ist. 
Hoffe mir kann jemand bei dem Problem helfen und mir sagen, wie man so eine "Factory" realisiert. 

Vllt ist es auch einfach ein bisschen zu spät und morgen hab ich etwas mehr Durchblick  :o 

Grüße

Generics und Reflection passen nicht zusammen, mit newInstance() immer generisch unsicher, damit ist zu leben,

Generics hilft gegen Casten bei Listen,
Generics hilft so dass du nur die richtigen Typen an die Generics-Methoden übergeben kannst und den Rückgabewert nicht casten musst,
das sind schon gute Dinge,
aber intern sehen die Generics-Methoden oft nicht so schön aus, ist ok, ArrayList tut sich auch etwas schwer intern mit Arrays

das Wohl der Vielen (beliebig viele Aufrufer/ Verwender der API) steht über dem Wohl der Wenigen (internen Methoden), Spock grüßt (ein letztes Mal)


welchen Typ du übergibst ist für das Neuerzeugen recht egal, jedenfalls auf dem Weg mit getClass(), das liefert immer die aktuelle Klasse

Hey, danke schonmal.

Also im Moment sieht meine Factory dann so aus:


	public <T extends IPrototype<T>> List<T> create(T prototype, int n) throws Exception {
		ArrayList<T> list = new ArrayList<T>();
		for (int j = 0; j < n; j++)
			list.add(create(prototype));
		return list;
	}

	public <T extends IPrototype<T>> T create(T prototype) throws Exception {
		Class<T> type = (Class<T>) prototype.getClass();
		return type.newInstance();
	}
}```
Das funktioniert auch erstmal soweit.

Der einzige noch vorhandenen Warning ist bei diesem letzten Cast:```Class<T> type = (Class<T>) prototype.getClass();``` Den kann ich also nicht wirklich loswerden? 
Es wundert mich auch ein bisschen, dass ich das noch casten muss. prototype ist ja vom Typ T, wieso sollte die Class dann nicht trivialerweise auch Class<T> sein?
Eclipse Fehlermeldung ist nicht ganz ersichtlich. 
> Type safety: Unchecked cast from Class<capture#1-of ? extends IPrototype> to Class<T>
 mit dem "capture#1"... .
[quote=SlaterB]welchen Typ du übergibst ist für das Neuerzeugen recht egal, jedenfalls auf dem Weg mit getClass(), das liefert immer die aktuelle Klasse[/quote]
Gibt es da also einen anderen Weg ohne "getClass()"? 

Grüße

Du solltest statt T prototype besser Class<T> prototypeClass übergeben.
Auf dieser Class Instanz kannst du dann direct newInstance() aufrufen und sparst dir den Cast.

Daran hatte ich auch schon gedacht. Allerdings müsste ich dann den Cast auf der aufrufenden Seite machen oder nicht?

Ich wollte mir dann Objekte erzeugen und musste es so machen:

Bar prototype = new Bar();
List<Bar> list = factory.create((Class<Bar>)prototype.getClass(), 10);

Jetzt spar ich mir den Cast in der Factory, aber muss ihn bei jedem Aufruf machen oder nicht? Vllt kommt man da auch drum rum.

Man wird an der einen oder anderen Stelle um einen Cast nicht drumrumkommen, weil “getClass” ja ein “Class<?>” liefert, und dieses Wildcard kriegt man anders nicht weg. Das wichtig(st)e ist, dass der Client (also der, der die Methode verwenden soll) nichts falsch machen kann.

Eine alternative wäre, dem Prototyp-inferface ne Methode zu geben, welches erlaubt weitere Prototypen anzulegen. Damit bräuchtest du keine Casts mehr und könntest auch Prototypen erstellen, welche Konstruktoren mit Parametern besitzen.

    E create();
}

class Test implements IPrototype<Test> {
    @Override
    public Test create() {
        return new Test();
    }
}

class Factory {
    static <T extends IPrototype<T>> List<T> create(T prototype, int count) {
        List<T> elements = new ArrayList<>();

        for(int i = 0; i < count; i++) {
            elements.add(prototype.create());
        }

        return elements;
    }
}```

Philosophisch: Die Stelle, die eine Liste erstellen und befüllen soll, kennt auch deren Typ - für alle anderen Stellen ist deren Typ über die Deklaration ersichtlich.

Also wozu sollen Obj erstellt werden, die vorher aus dem statischen Kontext nicht ersichtlich sind? Inhalt der Liste ist Sache des Aufrufers und Verwenders, nicht des Verwalters. Oder: -rin, -rin und -rin.