85 votes

Comment obtenir l'attribut `.class` d'un paramètre de type générique ?

La réponse acceptée à la question cette question décrit comment créer une instance de T en el Generic<T> classe. Il s'agit de passer un Class<T> au paramètre Generic et en appelant le newInstance de cette méthode.

Une nouvelle instance de Generic<Bar> est alors créé, et le paramètre Bar.class est transmise.

Que faites-vous si le paramètre de type générique pour le nouveau Generic n'est pas une classe connue comme Bar mais est lui-même un paramètre de type générique ? Supposons que j'aie une autre classe Skeet<J> et je voulais créer une nouvelle instance de Generic<J> à l'intérieur de cette classe. Ensuite, si j'essaie de passer dans J.class J'obtiens l'erreur de compilation suivante :

cannot select from a type variable.

Existe-t-il un moyen de contourner ce problème ?

Le bout de code spécifique qui déclenche l'erreur pour moi est le suivant :

public class InputField<W extends Component & WidgetInterface>
                                                 extends InputFieldArray<W>
{
  public InputField(String labelText)
  {
    super(new String[] {labelText}, W.class);
  }
  /* ... */
}

public class InputFieldArray<W extends Component & WidgetInterface>
                                                                 extends JPanel
{
   /* ... */
  public InputFieldArray(String[] labelText, Class<W> clazz)
                          throws InstantiationException, IllegalAccessException
  {
    /* ... */

    for (int i = 0 ; i < labelText.length ; i++) {
      newLabel = new JLabel(labelText[i]);
      newWidget = clazz.newInstance();
      /* ... */
    }
    /* ... */
  }
  /* ... */
}

L'erreur se produit parce que je ne peux pas écrire W.class . Existe-t-il un autre moyen de transmettre la même information ?

68voto

Paul Bellora Points 26524

L'utilisation .class sur un paramètre de type n'est pas autorisé - à cause de type d'effacement , W aura été effacé a Component au moment de l'exécution. InputField devra également prendre un Class<W> de l'appelant, comme InputFieldArray :

public InputField(String labelText, Class<W> clazz)
{
    super(new String[] {labelText}, clazz);
}

14voto

jdex Points 942

Si vous utilisez le GSON vous pouvez obtenir le type de T facilement en utilisant TypeToken . La documentation de la classe est disponible aquí :

J'ai procédé de la manière suivante :

C'est la définition de ma classe :

public class ManagerGeneric <T> {}

Cela fait partie de ma méthode :

// Get the type of generic parameter
Type typeOfT = new TypeToken<T>(){}.getType();
// Deserialize
T data = gson.fromJson(json, typeOfT);

12voto

hexafraction Points 16201

W peut ne pas être disponible en raison de l'effacement des caractères. Vous devez exiger qu'un Class<W> est transmise à la méthode. Vous obtenez un objet de classe et son générique garantit que seul W et aucune sous-classe n'est transmise, en raison de la covariance.

public InputField(String labelText, Class<W> cls)
{
    super(new String[] {labelText}, cls);
}

prendra W.class mais pas WSubtype.class .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X