2013-06-06 11 views
5

ho usato Java per un bel po 'di tempo, ma alcune cose non sono ancora molto chiaro per me, soprattutto quando si tratta di farmaci generici ...generici Java - Classe <?> costruttore problema argomento

Ecco la cosa: ho questa classe Search che sto usando (see here for details), che è costruito in questo modo:

public Search(Class<?> searchClass) {...} 

ulteriormente più, ho un wrapper generico parametrizzata intorno a questo, come segue:

public class HibernateSearch<E> extends Search implements Serializable { 
    public HibernateSearch(Class<E> entityClass) { 
     super(entityClass); 
    } 
    // ... omitted for brevity 
} 

Ora, ciò di cui ho bisogno è il seguente: Mi piacerebbe creare una classe parametrizzata, che contenga questa classe come campo, ad es.

public class BaseSelectorComposer<T> extends SelectorComposer<Window> { 

    private HibernateSearch<T> searchObject; 
    ... 
    @Override 
    public void doAfterCompose(Window comp) throws Exception { 
     super.doAfterCompose(comp); 
     this.searchObject = 
      new HibernateSearchObject<T>(now what...???); 
     ... 
    } 
    ... 
} 

Penso che il problema che sto affrontando sia evidente dall'esempio fornito.
Qualcuno può consigliare cosa si può fare qui, o qualche alternativa?

risposta

5

Il modo più semplice sarebbe quella di passare la responsabilità a chi instanciates realtà e utilizza le istanze di BaseSelectorComposer, vale a dire:

public class BaseSelectorComposer<T> extends SelectorComposer<Window> { 

    private HibernateSearch<T> searchObject; 
    private final Class<T> theType; 

    public BaseSelectorComposer(Class<T> token) { 
     theType = token; 
    } 

    ... 
    @Override 
    public void doAfterCompose(Window comp) throws Exception { 
     super.doAfterCompose(comp); 
     this.searchObject = new HibernateSearchObject<T>(theType); 
     ... 
    } 
    ... 
} 

Se il BaseSelectorComposer è una sottoclasse astratta, che è sempre e solo utilizzato come

class IntSelectorComposer extends BaseSelectorComposer<Integer> { 
    ... 
} 

per esempio, come classe di base per le classi, che "legare" i parametri di tipo, ci sono modi per obtain the type information via reflection (anche se questo è incredibilmente brutto, dal momento che questo non è molto ben supportato nell'API IMHO).

1

In generale, questo è uno scenario difficile da eseguire. Provenendo da uno sfondo di .NET, ho trovato personalmente pochissimi casi in cui ho potuto risolvere questo problema, dal momento che Java non supporta la risoluzione statica di tipo generico (come ad esempio in .NET dove è possibile utilizzare typeof(T)).

Per aggirare questo problema, consiglio di trovare un modo per ottenere la classe esternamente o un'istanza di quella classe. Una possibile soluzione potrebbe essere quella di cambiare il metodo doAfterCompose in uno dei seguenti modi:

@Override 
public void doAfterCompose(Window comp, Class<?> entityClass) throws Exception { 
    super.doAfterCompose(comp); 
    this.searchObject = 
     new HibernateSearchObject<T>(entityClass); 
    ... 
} 

oppure

@Override 
public void doAfterCompose(Window comp, SomeEntity entity) throws Exception { 
    super.doAfterCompose(comp); 
    this.searchObject = 
     new HibernateSearchObject<T>(entity.getClass()); 
    ... 
} 

Se non è possibile modificare la firma del metodo (vedo che è un override), prova a utilizzare un membro della classe BaseSelectorComposer<T> che manterrà l'istanza desiderata di Class<?>.

public class BaseSelectorComposer<T> extends SelectorComposer<Window> { 
    private Class<?> entityClass; 

    public BaseSelectorComposer<T>(Class<?> entityClasss) { 
     this.entityClass = entityClass; 
    } 

    .... 
    @Override 
    public void doAfterCompose(Window comp) throws Exception { 
     super.doAfterCompose(comp); 
     this.searchObject = 
      new HibernateSearchObject<T>(this.entityClass); 
     ... 
    } 
} 
Problemi correlati