Mam klasy szablon następująco:instancji obiektu typu parametru
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Jak utworzyć nową instancję T w mojej klasie?
Mam klasy szablon następująco:instancji obiektu typu parametru
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Jak utworzyć nową instancję T w mojej klasie?
Po wymazaniu typu wszystko, co wiadomo na temat T
, jest podklasą Object
. Musisz określić fabrykę, aby utworzyć instancje T
.
Jedno podejście przydałoby się 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();
}
}
Wykorzystanie może wyglądać następująco:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatywnie, można podać Class<T>
obiekt, a następnie użyć refleksji.
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();
}
}
Jeśli jesteś gotów do podklasy można uniknąć usunięcia, a także, sprawdź http://www.artima.com/weblogs/viewpost.jsp?thread=208860
może to być więcej niż wagi ciężkiej co szukasz, ale będzie również działać. Zauważ, że jeśli podejmiesz takie podejście, bardziej sensownym byłoby wstrzyknięcie fabryki do MyClass, gdy zostanie ona skonstruowana, zamiast przekazywania jej do metody za każdym razem, gdy zostanie wywołana.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
Dobre, nieodblaskowe podejście; odbicie nie zawsze jest opcją. myMethod powinien być w stanie zaakceptować MyFactory extends T>, prawda? – erickson
Dobra rozmowa - będziesz chciał umieścić ograniczony znak wieloznaczny w fabryce, aby umożliwić tworzenie obiektów typu T i podklas T w myMethod(). –
Innym nieodblaskowym podejściem jest użycie hybrydowego wzoru Builder/Abstract Factory.
W Effective Java, Joshua Bloch podchodzi wzoru Builder w szczegółach, i popiera ogólny interfejs Builder:
public interface Builder<T> {
public T build();
}
betonowe budowniczowie mogą implementować ten interfejs, a zajęcia na zewnątrz można użyć betonu budowniczy, aby skonfigurować Builder zgodnie z wymaganiami. Budowniczy może zostać przekazany do MyClass jako Builder<T>
.
Używając tego wzorca, można uzyskać nowe instancje T
, nawet jeśli T
ma parametry konstruktora lub wymaga dodatkowej konfiguracji. Oczywiście będziesz potrzebował jakiegoś sposobu przekazania Buildera do MyClass. Jeśli nie możesz przekazać niczego do MyClass, to Builder i Abstract Factory są niedostępne.
Klasa classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Co Pakiet 'Supplier' znajduje się w? 'MyClass (klasa extends T> impl)' musi zadeklarować 'wyrzuca NoSuchMethodException' do kompilacji. Twoja odpowiedź nie jest niestety przyjazna dla początkującego języka Java. – user927387
@ user927387 'java.util.function.Supplier' – erickson