Question

J'ai une affaire assez simple où je fais une affectation générique de base:

final Detail detail = field.getAnnotation(Detail.class);
final String example = detail.example();
final Class<?> type = field.getType();
if (List.class.isAssignableFrom(type))
                    ...
else if (Enum.class.isAssignableFrom(type))
    setValue(contract, field, Enum.valueOf(type, example));
else if (...)
.....

Enum.valueOf () est un peu difficile d'appeler, dans mon cas, l'erreur est:

  

valueOf (java.lang.Class, java.lang.String) dans java.lang.Enum ne peut pas être appliquée à (java.lang.Class, java.lang.String)

Cela rend parfaitement logique puisque le type est Class<Object>. Mais depuis Enum est CRTP, je ne peux pas trouver un bon moyen de le type transtypée pour le compilateur heureux. Est-ce en utilisant le type brut Enum.valueOf((Class)type, example)) la seule réponse? Il me donne 2 avertissements au lieu d'un seul.

Était-ce utile?

La solution

La ligne suivante fera avec un seul avertissement:

...
setValue( contract, field, Enum.valueOf( type.asSubclass( Enum.class ), example ) );
...

Autres conseils

Vous pouvez écrire une méthode d'aide pour capturer un type « T » qui satisfait l'exigence de Enum:

private <T extends Enum<T>> T helper(Class<?> type, String example) {
    return Enum.valueOf((Class<T>)type, example);
}

cela ne devrait avoir un avertissement

et vous pouvez l'utiliser comme

else if (Enum.class.isAssignableFrom(type))
    setValue(contract, field, helper(type, example));

Edit: D'accord, alors que diriez-vous:

private <T extends Enum<T>> Object helper(Class<?> type, String example) {
    return Enum.valueOf((Class<T>)type, example);
}

Je ne pense pas qu'il est possible de supprimer les avertissements du compilateur

Le meilleur scénario est de réduire toutes les erreurs dans un comme @tangens fait.

trouvé deux sujets du forum qui montrent des réponses infructueuses et explique le pourquoi un peu plus.

Je mis en place un exemple complet pour démontrer la question que je le vois.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.List;

public class Test {
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public @interface Detail {
    String example();
  }

  public enum ExampleEnum {
    FOO_BAR, HELLO_WORLD
  }

  @Detail(example = "FOO_BAR")
  public ExampleEnum test;

  public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    populate(new Test());
  }

  public static void populate(Object o) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {
    final Field field = o.getClass().getField("test");
    final Detail detail = field.getAnnotation(Detail.class);
    System.out.println("Annotation = " + detail);
    final String example = detail.example();
    final Class<?> type = field.getType();
    System.out.println("Field Class = " + type.getName());
    if (List.class.isAssignableFrom(type)) {
    } else if (Enum.class.isAssignableFrom(type)) {
      Class<? extends Enum> enumType = type.asSubclass(Enum.class); // Enum is a raw type. References to generic type Enum<E> should be parameterized
      Enum val = Enum.valueOf(enumType, example); // 1) Enum is a raw type. References to generic type Enum<E> should be parameterized
                                                  // 2) Type safety: Unchecked invocation valueOf(Class<capture#7-of ? extends Enum>, String) of the generic
                                                  //    method valueOf(Class<T>, String) of type Enum
      field.set(o, val);
    }
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top