Aşağıdaki gibi bir şablon sınıfım var:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Sınıfımda yeni bir T örneğini nasıl oluşturabilirim?
Yanıtlar:
Tür silme işleminden sonra, bilinen T
tek şey onun bazı alt sınıfı olduğudur Object
. Örneklerini oluşturmak için bazı fabrika belirtmeniz gerekir T
.
Bir yaklaşım a kullanabilir 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();
}
}
Kullanım şöyle görünebilir:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Alternatif olarak, bir Class<T>
nesne sağlayabilir ve ardından yansımayı kullanabilirsiniz.
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
Yansıtıcı olmayan başka bir yaklaşım, hibrit bir Oluşturucu / Soyut Fabrika modeli kullanmaktır.
Etkili Java'da Joshua Bloch, Builder modelini ayrıntılı olarak ele alır ve genel bir Builder arayüzünü savunur:
public interface Builder<T> {
public T build();
}
Beton inşaatçılar bu arabirimi uygulayabilir ve dış sınıflar, Oluşturucu'yu gerektiği gibi yapılandırmak için beton oluşturucuyu kullanabilir. Oluşturucu, MyClass'a bir Builder<T>
.
Bu kalıbı kullanarak , yapıcı parametreleri olsa veya ek yapılandırma gerektirse T
bile yeni örneklerini alabilirsiniz T
. Elbette, Builder'ı MyClass'a geçirmek için bir yola ihtiyacınız olacak. MyClass'a hiçbir şey aktaramazsanız, Builder ve Abstract Factory devre dışıdır.
Bu, aradığınızdan daha ağır olabilir, ancak aynı zamanda işe yarayacaktır. Bu yaklaşımı kullanırsanız, fabrikayı her çağrıldığında yönteminize geçirmek yerine, inşa edildiğinde MyClass'a enjekte etmenin daha mantıklı olacağını unutmayın.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
Alt sınıfa istekli iseniz, silmeyi de önleyebilirsiniz, http://www.artima.com/weblogs/viewpost.jsp?thread=208860 adresine bakın.
Sınıf classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Supplier
bulunuyor? "MyClass (Class <? Extends T> impl)", derlenmek için "NoSuchMethodException" atar bildirmelidir. Cevabınız ne yazık ki Java acemi için uygun değil.