2008-11-18 8 views

Répondre

57

Après l'effacement du type, tout ce que l'on sait sur T 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 un 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(); 
    } 

} 

Utilisation pourrait ressembler à ceci:

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

Vous pouvez fournir un objet Class<T>, et ensuite 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(); 
    } 

} 
+0

Quel package le 'Supplier' est situé dans? 'MyClass (Classe impl)' doit déclarer 'throws NoSuchMethodException' à compiler. Votre réponse n'est malheureusement pas favorable à Java débutant. – user927387

+0

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

10

Cela peut être plus lourd que ce que vous cherchez, mais il fonctionnera également. Notez que si vous adoptez cette approche, il serait plus logique d'injecter l'usine dans MyClass lorsqu'elle est construite au lieu de la transmettre à 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() 
    } 
} 
+1

Bonne approche non réfléchissante; la réflexion n'est pas toujours une option. myMethod devrait être en mesure d'accepter un MyFactory , non? – erickson

+0

Bon appel - vous devez placer un caractère générique délimité en usine pour permettre la création d'objets de type T et de sous-classes de T dans myMethod(). –

11

Une autre approche non-réfléchissante consiste à utiliser un motif hybride Builder/Usine abstraite.

En Java efficace, Joshua Bloch va sur le motif Builder en détail, et préconise une interface Builder générique:

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

constructeurs en béton peuvent implémenter cette interface, et en dehors des cours peuvent utiliser le générateur de béton pour configurer la Constructeur au besoin. Le constructeur peut être transmis à MyClass en tant que Builder<T>. En utilisant ce modèle, vous pouvez obtenir de nouvelles instances de T, même si 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 Builder dans MyClass. Si vous ne pouvez rien transférer dans MyClass, alors Builder et Abstract Factory sont sortis.

1

Classe classOfT

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