Aller au contenu

[ Java ] Introspection sur une classe générique ?


lmarin

Messages recommandés

Bonjours à tous,

J'ai une classe qui contient une liste d'objet dont le type est passer en paramétre générique de ma classe ( cf code )

public class MaListe<T> extends UneClasseAbstraite<T> {
private List<T> listes;

...

@Override
public void maMethodeDeMaClasseAbstraite( T obj) {
...
}

}

Je souhaiterais faire de l'introspection sur les objets contenus dans ma liste de Type "T", comment faire ?

J'ai tenté de faire de taper sur du this.getClass().getTypeParameters() sans résultat.

Merci !

Lien vers le commentaire
Partager sur d’autres sites

Quel objet en paramètre ?

Tu veux dire dans maMethodeDeMaClasseAbstraite ?

Si tu veux introspecter obj, alors tu dois faire obj.getClass()

Après si tu commences à faire de l'instrospection dans une classe générique, demande toi bien si tu ne fais pas une erreur de conception.

Car le but de la généricité est justement de ne pas faire cela.

Lien vers le commentaire
Partager sur d’autres sites

Je souhaiterais introspecter depuis MaListe l'objet passé en paramètre, à sa voir T, hors T.getClass() n'existe pas :)

Bien sûr que non, mais il est possible que T.class existe (comme quand tu fais String.class, mais je n'en mettrai pas ma main à couper)

Dans tous les cas, tu peux appeler getClass sur l'instance (et non la classe) de T que tu reçois en paramètre !

Lien vers le commentaire
Partager sur d’autres sites

Dans ce cas, tu n'as pas d'autre choix que de passer la classe en paramètre.

public MaListe ( Class<T> theClass )

et introspecter dessus.

Il faut bien se rappeler qu'il ne reste aucune référence aux classes génériques une fois le code compilé. Donc T.class n'a aucun sens puisque T sera transformé en Object une fois le travail du compilateur effectué.

Maintenant, ce n'est pas une bonne pratique que d'introspecter. Il faut que ça reste une exception dans le code ....

Lien vers le commentaire
Partager sur d’autres sites

Justement je pensais que si tu faisais T.class le compilo aurait remplacé par String.class si tu avais utilisé String et ça roulez... Mais bon ça fait tellement de temps que j'ai pas touché à Java, quand j'en faisait y avait pas encore de génériques :francais:

Non mais sinon c'est vrai que si tu peux éviter d'utiliser l'introspection c'est mieux. En plus c'est méga lent en général.

Lien vers le commentaire
Partager sur d’autres sites

Non non :francais:

T est tout simplement mis de côté et inutilisé après pour que le code compilé puisse être exécuté avec une JVM 1.4.

Les performances de l'introspection ont été largement améliorées dans les versions 1.5 et 1.6 mais il faut bien réfléchir à pourquoi on en a besoin car il y a bien souvent une solution autre (design pattern) qui permet d'arriver au même résultat de façon plus élégante.

Lien vers le commentaire
Partager sur d’autres sites

Les types génériques existent uniquement dans le code source, pour permettre au compilateur de s'assurer que, par exemple, on ne place que des objets du type autorisé dans une collection. Le but étant d'éviter au maximum les ClassCastException lorsqu'on tente de récupérer les objets depuis ladite collection.

Mais, pour des raisons de rétrocompatibilité avec la base de code existante (les applis en entreprise), le compilateur supprime toutes ces informations de typage : c'est ce qu'on appelle la phase de "type erasure".

Au runtime, les types génériques n'existent donc plus. Ce que tu obtiens en appelant getTypeParameters(), c'est uniquement les noms des placeholders (le "T" de UneClasseAbstraite<T>).

Lien vers le commentaire
Partager sur d’autres sites

Dans l'idée, je voudrais juste me faire un TableModel par défaut qui irait faire de l'introspection sur les objets métiers à afficher pour mettre les attributs publics dans les colonnes. L'objet métier étant passé a ma classe en générique est donc l'inspection sur l'objet générique.

La seule solution que j'ai pu entre voir consiste a faire de l'introspection sur une méthode de ma classe qui prends en argument ou en retour un générique, et je peux pas dire que je trouve cette solution très glamour....

Lien vers le commentaire
Partager sur d’autres sites

  • 2 mois après...

Bonjour,

justement je cherche à faire ça, c'est à dire, récupérer la class de T passé en argument de TableModelPerso(List<T> list). Ceci dans le but de faire de l'introspection pour les headers de ma JTable.

public TableModelPerso(List<T> list) {
	super();
	Object o = null;
	titres = new ArrayList<String>();
	data = new Vector<Vector<Object>>();
	o = list.get(0);
	Class oClass =o.getClass();
	Field[] oFields = oClass.getDeclaredFields();
	for (int i = 0; i < oFields.length; i++) {
		Field champs = oFields[i];
		if (champs.isAnnotationPresent(TableHeader.class)) {
			Annotation tableHeaderAnnot = champs.getAnnotation(TableHeader.class);
			TableHeader header = (TableHeader) tableHeaderAnnot;
			while (titres.size() < header.index()) {
				titres.add(null);
				data.add(null);
			}
			titres.set(header.index() - 1, header.value());...

Je précise que la classe TableHeader est une classe héritant de Annotation. Dans la classe T (que je cherche à obtenir) j'ai ajouté des annotations précisant le titre de la colonne ainsi que son index par défaut.

Dans ce bout de code, la chose qui me dérange est que si list est vide et bien je me récupère une exception, et même si je la capte je ne peux pas faire d'introspection, donc j'aurais un tableau sans titres de colonne.

Un petit éclaircissement, ou une autre façon d'aborder ceci, serait le bienvenue.

Merci d'avance

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...