J'ai une classe de modèle comme suit:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Comment créer une nouvelle instance de T dans ma classe?
J'ai une classe de modèle comme suit:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Comment créer une nouvelle instance de T dans ma classe?
Réponses:
Après l'effacement de type, tout ce que l'on sait, T
c'est qu'il s'agit d'une sous-classe de Object
. Vous devez spécifier une fabrique pour créer des instances de T
.
Une approche pourrait utiliser 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();
}
}
L'utilisation pourrait ressembler à ceci:
MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);
Vous pouvez également fournir un Class<T>
objet, puis utiliser la réflexion.
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
Une autre approche non réfléchissante consiste à utiliser un modèle hybride Builder / Abstract Factory.
Dans Effective Java, Joshua Bloch passe en revue le modèle Builder en détail et préconise une interface Builder générique:
public interface Builder<T> {
public T build();
}
Les constructeurs concrets peuvent implémenter cette interface, et les classes extérieures peuvent utiliser le constructeur concret pour configurer le constructeur selon les besoins. Le générateur peut être transmis à MyClass en tant que fichier Builder<T>
.
En utilisant ce modèle, vous pouvez obtenir de nouvelles instances de T
, même si elle T
a des paramètres de constructeur ou nécessite une configuration supplémentaire. Bien sûr, vous aurez besoin d'un moyen de passer le générateur dans MyClass. Si vous ne pouvez rien transmettre à MyClass, alors Builder et Abstract Factory sont sortis.
Cela peut être plus lourd que ce que vous recherchez, mais cela fonctionnera également. Notez que si vous adoptez cette approche, il serait plus logique d'injecter la fabrique dans MyClass lorsqu'elle est construite au lieu de la passer dans votre méthode à chaque fois qu'elle est appelée.
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
Si vous êtes prêt à sous-classer, vous pouvez également éviter l'effacement, consultez http://www.artima.com/weblogs/viewpost.jsp?thread=208860
Classe classOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Supplier
se trouve-t-il? `MyClass (Class <? Extend T> impl)` doit déclarer `throws NoSuchMethodException` pour être compilé. Votre réponse n'est malheureusement pas adaptée aux débutants en Java.