2008-11-18 14 views

Antwort

57

Nach Typ löschen, ist alles, was über T bekannt ist, dass es eine Unterklasse von Object ist. Sie müssen eine Factory angeben, um Instanzen von T zu erstellen.

Ein Ansatz könnte ein Supplier<T> verwenden:

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(); 
    } 

} 

Verbrauch könnte wie folgt aussehen:

MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new); 

Alternativ können Sie bieten eine Class<T> Objekt, und dann 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(); 
    } 

} 
+0

Welches Paket der 'Supplier' in ist? 'MyClass (Klasse impl)' muss deklarieren 'throws NoSuchMethodException' zum Kompilieren. Ihre Antwort ist leider nicht Java-freundlich. – user927387

+0

@ user927387 'java.util.function.Supplier' – erickson

10

Dies kann mehr Schwergewicht sein als das, was Sie suchen, aber es wird auch funktionieren. Beachten Sie, dass es bei einer solchen Vorgehensweise sinnvoller wäre, die Factory beim Erstellen in MyClass zu injizieren, anstatt sie bei jedem Aufruf an Ihre Methode zu übergeben.

+1

Guter, nicht reflektierender Ansatz; Reflexion ist nicht immer eine Option. myMethod sollte in der Lage sein, eine MyFactory , richtig zu akzeptieren? – erickson

+0

Guter Aufruf - Sie sollten einen beschränkten Platzhalter in der Factory platzieren, um Objekte vom Typ T und Unterklassen von T in myMethod() erstellen zu lassen. –

11

Ein weiterer nicht reflektierender Ansatz ist die Verwendung eines hybriden Builder/Abstract Factory-Musters.

In Effective Java, Joshua Bloch geht über die Builder-Muster im Detail, und spricht sich für eine generische Builder-Schnittstelle:

public interface Builder<T> { 
    public T build(); 
} 

Betonbauer diese Schnittstelle implementieren können, und außerhalb Klassen der Betonbauer können die konfigurieren Builder nach Bedarf. Der Builder kann als Builder<T> an MyClass übergeben werden.

Mit diesem Muster können Sie neue Instanzen von T erhalten, auch wenn T Konstruktorparameter hat oder zusätzliche Konfiguration erfordert. Natürlich benötigen Sie eine Möglichkeit, den Builder in MyClass zu übergeben. Wenn Sie MyClass nichts übergeben können, sind Builder und Abstract Factory nicht verfügbar.

1

Klasse classOfT

 try { 
      t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
Verwandte Themen