Question

Avant que je regarde à travers ma structure de données générique pour l'index d'une valeur, je voudrais voir si elle est même une instance du type this a été paramétrés à.

Mais Eclipse se plaint quand je fais ceci:

@Override
public int indexOf(Object arg0) {
    if (!(arg0 instanceof E)) {
        return -1;
    }

Ceci est le message d'erreur:

  

Impossible d'effectuer instanceof vérifier contre paramètre de type E. Utilisez plutôt son effacement objet car les informations de type générique sera effacé lors de l'exécution

Quelle est la meilleure façon de le faire?

Était-ce utile?

La solution

Le message d'erreur dit tout. Lors de l'exécution, le type est parti, il n'y a aucun moyen de vérifier cela.

Vous pouvez l'attraper en faisant une usine pour votre objet comme ceci:

 public static <T> MyObject<T> createMyObject(Class<T> type) {
    return new MyObject<T>(type);
 }

Et puis dans le magasin de constructeur de type qui, si variable de l'objet afin que votre méthode pourrait ressembler à ceci:

        if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass()))
        {
            return -1;
        }

Autres conseils

Deux options pour la vérification du type d'exécution avec les génériques:

Option 1 - Corrupt votre constructeur

Supposons que vous surchargez indexOf (...), et que vous voulez vérifier le type juste pour la performance, pour vous sauver itérer la collection.

Faire un constructeur sale comme ceci:

public MyCollection<T>(Class<T> t) {

    this.t = t;
}

Ensuite, vous pouvez utiliser IsAssignableFrom pour vérifier le type.

public int indexOf(Object o) {

    if (
        o != null &&

        !t.isAssignableFrom(o.getClass())

    ) return -1;

//...

Chaque fois que vous instanciez votre objet que vous auriez à vous répéter:

new MyCollection<Apples>(Apples.class);

Vous pouvez décider qu'il est pas la peine. Dans la mise en œuvre de ArrayList.indexOf (...) , ils ne vérifient pas que les matchs de type.

Option 2 - Laissez échouer

Si vous avez besoin d'utiliser une méthode abstraite qui nécessite votre type inconnu, tout ce que vous voulez vraiment est pour le compilateur d'arrêter de pleurer sur les instanceof . Si vous avez une méthode comme ceci:

protected abstract void abstractMethod(T element);

Vous pouvez l'utiliser comme ceci:

public int indexOf(Object o) {

    try {

        abstractMethod((T) o);

    } catch (ClassCastException e) {

//...

Vous caster l'objet à T (votre type générique), juste pour tromper le compilateur. Votre casting ne fait rien à l'exécution , mais vous aurez toujours obtenir un ClassCastException lorsque vous essayez de passer le mauvais type d'objet dans votre méthode abstraite.

NOTE 1: Si vous faites des moulages non vérifiées supplémentaires dans votre méthode abstraite, vos ClassCastExceptions se faire prendre ici. Cela pourrait être bon ou mauvais, alors pensez-y.

NOTE 2: Vous obtenez un chèque null gratuit lorsque vous utilisez instanceof . Puisque vous ne pouvez pas l'utiliser, vous devrez peut-être vérifier null avec vos mains nues.

Ancien poste, mais d'une manière simple instanceOf générique de vérification.

public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
    return clazz.isInstance(targetClass);
}

A condition de votre classe étend une classe avec un paramètre générique, vous pouvez également obtenir ce lors de l'exécution par la réflexion, et ensuite utiliser que pour la comparaison, i.e..

class YourClass extends SomeOtherClass<String>
{

   private Class<?> clazz;

   public Class<?> getParameterizedClass()
   {
      if(clazz == null)
      {
         ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
          clazz = (Class<?>)pt.getActualTypeArguments()[0];
       }
       return clazz;
    }
}

Dans le cas ci-dessus, lors de l'exécution, vous obtiendrez String.class de getParameterizedClass (), et il met en cache afin de ne pas les frais généraux de réflexion sur plusieurs contrôles. Notez que vous pouvez obtenir les autres types paramétrés par l'indice de la méthode ParameterizedType.getActualTypeArguments ().

J'ai eu le même problème et voici ma solution (très humble, @george: cette fois la compilation et de travail ...).

Mon probem était à l'intérieur d'une classe abstraite qui implémente observateur. La mise à jour des feux Observable méthode (...) avec la classe d'objets qui peuvent être tout type d'objet.

Je veux seulement handler objets de type T

La solution est de passer la classe au constructeur afin de pouvoir comparer les types à l'exécution.

public abstract class AbstractOne<T> implements Observer {

  private Class<T> tClass;
    public AbstractOne(Class<T> clazz) {
    tClass = clazz;
  }

  @Override
  public void update(Observable o, Object arg) {
    if (tClass.isInstance(arg)) {
      // Here I am, arg has the type T
      foo((T) arg);
    }
  }

  public abstract foo(T t);

}

Pour la mise en œuvre que nous venons de passer la classe au constructeur

public class OneImpl extends AbstractOne<Rule> {
  public OneImpl() {
    super(Rule.class);
  }

  @Override
  public void foo(Rule t){
  }
}

Ou vous pourriez attraper un tentative avortée de jeter dans E par exemple.

public int indexOf(Object arg0){
  try{
    E test=(E)arg0;
    return doStuff(test);
  }catch(ClassCastException e){
    return -1;
  }
}

Techniquement vous ne devriez pas avoir à, c'est le point de génériques, de sorte que vous pouvez faire la vérification de type compilation:

public int indexOf(E arg0) {
   ...
}

mais le @Override peut être un problème si vous avez une hiérarchie de classes. Sinon, voir la réponse de Yishai.

Le type d'exécution de l'objet est une condition relativement arbitraire à filtrer. Je suggère garder ces muckiness loin de votre collection. Ceci est simplement réalisé en ayant votre délégué de collection à un filtre passé dans une construction.

public interface FilterObject {
     boolean isAllowed(Object obj);
}

public class FilterOptimizedList<E> implements List<E> {
     private final FilterObject filter;
     ...
     public FilterOptimizedList(FilterObject filter) {
         if (filter == null) {
             throw NullPointerException();
         }
         this.filter = filter;
     }
     ...
     public int indexOf(Object obj) {
         if (!filter.isAllows(obj)) {
              return -1;
         }
         ...
     }
     ...
}

     final List<String> longStrs = new FilterOptimizedList<String>(
         new FilterObject() { public boolean isAllowed(Object obj) {
             if (obj == null) {
                 return true;
             } else if (obj instanceof String) {
                 String str = (String)str;
                 return str.length() > = 4;
             } else {
                 return false;
             }
         }}
     );
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top