Ich habe eine Vorlagenklasse wie folgt:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Wie erstelle ich eine neue Instanz von T in meiner Klasse?
Ich habe eine Vorlagenklasse wie folgt:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Wie erstelle ich eine neue Instanz von T in meiner Klasse?
Antworten:
Nach dem Löschen des Typs ist nur bekannt, T
dass es sich um eine Unterklasse von handelt Object
. Sie müssen eine Factory angeben, um Instanzen von zu erstellen T
.
Ein Ansatz könnte Folgendes verwenden Supplier<T>
:
class MyClass<T> {
private final Supplier<? extends T> ctor;
private T field;
MyClass(Supplier<? extends T> ctor) {
this.ctor = Objects.requireNonNull(ctor);
}
public void myMethod() {
field = ctor.get();
}
}
Die Verwendung könnte folgendermaßen aussehen:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternativ können Sie ein Class<T>
Objekt bereitstellen und dann die Reflexion verwenden.
class MyClass<T> {
private final Constructor<? extends T> ctor;
private T field;
MyClass(Class<? extends T> impl) throws NoSuchMethodException {
this.ctor = impl.getConstructor();
}
public void myMethod() throws Exception {
field = ctor.newInstance();
}
}
java.util.function.Supplier
Ein anderer nicht reflektierender Ansatz ist die Verwendung eines hybriden Builder / Abstract Factory-Musters.
In Effective Java geht Joshua Bloch das Builder-Muster im Detail durch und befürwortet eine generische Builder-Oberfläche:
public interface Builder<T> {
public T build();
}
Concrete Builder können diese Schnittstelle implementieren, und externe Klassen können den Concrete Builder verwenden, um den Builder nach Bedarf zu konfigurieren. Der Builder kann als an MyClass übergeben werden Builder<T>
.
Mit diesem Muster können Sie neue Instanzen von abrufen T
, auch wenn T
Konstruktorparameter vorhanden sind oder eine zusätzliche Konfiguration erforderlich ist. Natürlich benötigen Sie eine Möglichkeit, den Builder an MyClass zu übergeben. Wenn Sie nichts an MyClass übergeben können, sind Builder und Abstract Factory nicht verfügbar.
Dies ist möglicherweise schwerer als das, was Sie suchen, aber es wird auch funktionieren. Beachten Sie, dass es bei diesem Ansatz sinnvoller ist, die Factory bei der Erstellung in MyClass einzufügen, als sie bei jedem Aufruf an Ihre Methode zu übergeben.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
Wenn Sie bereit sind, eine Unterklasse zu erstellen, können Sie auch das Löschen vermeiden. Weitere Informationen finden Sie unter http://www.artima.com/weblogs/viewpost.jsp?thread=208860
Klasse classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Supplier
befindet sich das? `MyClass (Class <? Erweitert T> impl)` muss deklarieren `löst NoSuchMethodException` aus, um kompiliert zu werden. Ihre Antwort ist leider nicht freundlich zu Java-Anfängern.