2016-03-07 2 views
3

Je dois invoquer les méthodes accesseur de champ, c'est-à-dire le getter d'une énumération générique, mais je n'arrive pas à comprendre comment appeler les méthodes, ou plus précisément comment passer une énumération générique en paramètre invoke-method.Appel de getters d'une énumération générique

Merci d'avance, toute aide est appréciée.

C'est ce que j'aimerais faire plus ou moins.

public void(Class<? extends Enum<?>> enumType) { 
    Enum<?>[] enumConstants = enumType.getEnumConstants(); 
    String[] text = new String[enumConstants.length]; 
    String[] names = new String[enumConstants.length]; 
    for (int i = 0; i < enumConstants.length; i++) { 
     Method[] methods = enumConstants[i].getClass().getDeclaredMethods(); 
     for (Method m: enumConstants[i].getClass().getDeclaredMethods()) { 
      System.out.println(enumConstants[i].name() + ": " + m.getName() + "()"); 
      try { 
       if (GET_KEY_METHOD_NAME.equalsIgnoreCase(m.getName())) { 
        Object value = m.invoke(I HAVE NO IDEA WHAT TO PUT HERE, ""); 
        System.out.println(value.toString()); 
       } 
       if (GET_VALUE_METHOD_NAME.equalsIgnoreCase(m.getName())) { 
        Object value = m.invoke(I HAVE NO IDEA WHAT TO PUT HERE, ""); 
        System.out.println(value.toString()); 
       } 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
      } catch (InvocationTargetException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 

} 
+0

Eh bien, la première supposition évidente est 'm.invoke (enumConstants [i])', sans aucun '' "' 'car un getter ne devrait avoir aucun paramètre. Est-ce que cela échoue? Si oui, que dit le message d'erreur? –

+0

Avez-vous essayé de mettre enumConstants [i] sur "JE N'AI AUCUNE IDEE QUOI METTRE ICI"? – andrucz

Répondre

2

Les paramètres de la méthode Method.invoke sont toujours l'instance la méthode est appelée pour, suivie de la liste des paramètres.

Object value = m.invoke(enumConstants[i]); 

est probablement ce dont vous avez besoin.

Aussi, vous devez ajouter un paramètre de type à la méthode:

public <T extends Enum<T>> void myMethod(Class<T> enumType) { 
    T[] enumConstants = enumType.getEnumConstants(); 

BTW: Avez-vous envisagé d'utiliser un interface contenant ces méthodes? Cela vous permettrait d'accéder aux méthodes sans avoir à utiliser la réflexion.

Jetez également un coup d'oeil à la méthode getDeclaredMethod et gardez à l'esprit que les constantes enum peuvent être des instances d'une sous-classe de la classe enum, vous devriez donc utiliser les méthodes ne contenant pas Declared. Retrouvez également les méthodes de la classe ENUM, non pas pour les classes individuelles pour moins lookups:

Par exemple, considérons les éléments suivants:

public enum MyEnum implements M1M2Interface { 
    ONE() { 

     @Override 
     public String m1(String s) { 
      return "1"; 
     } 

    }, TWO() { 

     @Override 
     public int m2(BigInteger i) { 
      return 2; 
     } 

    } 
    ; 

} 

public interface M1M2Interface { 
    default String m1(String s) { 
     return "2"; 
    } 

    default int m2(BigInteger i) { 
     return 1; 
    } 
} 
public static <T extends Enum<T>> void testEnum(Class<T> enumType) throws NoSuchMethodException { 
    T[] enumConstants = enumType.getEnumConstants(); 
    Method m1 = enumType.getMethod("m1", String.class); 
    Method m2 = enumType.getMethod("m2", BigInteger.class); 

    for (int i = 0; i < enumConstants.length; i++) { 
     System.out.println(enumConstants[i].name() + ":"); 
     try { 
      System.out.println(" m1:" + m1.invoke(enumConstants[i], "Hello World")); 
      System.out.println(" m2:" + m2.invoke(enumConstants[i], (BigInteger) null)); 
     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

getDeclaredMethod ne fonctionnerait pas ici, étant donné que les méthodes pourront être déclarés/mis en oeuvre par:

  • L'interface (déclarée seulement avant java 8)
  • la classe ENUM
  • la constante enum (s'il n'y a pas de déclaration à un « niveau supérieur » la méthode ne peut pas être accessible à l'aide EnumName.CONSTANT_NAME.methodName() il est donc peu susceptible d'être fait ...)
+0

Cela a fait le travail en premier lieu. Réservoirs mille fois. Oui, je pensais utiliser une interface, mais d'une manière ou d'une autre l'architecture de cette application relativement ancienne m'empêche de faire ça ... peut-être un peu de temps. – Horn1347

1

La réflexion est rarement réponse correcte à n'importe quoi. Envisagez d'avoir vos classes enum implémentent une interface commune, comme StandardCopyOption et Month faire.

Si vous ne pouvez pas modifier les classes enum, et si vous utilisez Java 8, vous pouvez passer la méthode getter comme argument:

public <E extends Enum<E>> E findMatch(Class<E> enumClass, 
             Function<E, String> nameGetter, 
             Predicate<String> matcher) { 
    for (E value : EnumSet.allOf(enumClass)) { 
     String name = nameGetter.apply(value); 
     if (matcher.test(name)) { 
      return value; 
     } 
    } 

    return null; 
} 

Exemple d'utilisation:

public static enum Season { 
    SPRING("Spr"), 
    SUMMER("Sum"), 
    FALL("Fal"), 
    WINTER("Win"); 

    private final String abbreviation; 

    private Season(String abbrev) { 
     this.abbreviation = abbrev; 
    } 

    public getAbbreviation() { 
     return abbreviation; 
    } 
} 

public void doStuff() { 
    // ... 

    String abbrToFind = "Sum"; 
    Season match = findMatch(Season.class, 
     Season::getAbbreviation, 
     Predicate.isEqual(abbrToFind)); 
} 

Si vous utilisez une version antérieure à Java 8, vous pouvez toujours faire la même chose, mais vous devrez définir et implémenter les interfaces vous-même:

public interface Function<A, B> { 
    B apply(A input); 
} 

public interface Predicate<T> { 
    boolean test(T value); 
} 

public void doStuff() { 
    // ... 

    final String abbrToFind = "Sum"; 
    Season match = findMatch(Season.class, 
     new Function<Season, String>() { 
      @Override 
      public String apply(Season season) { 
       return season.getAbbreviation(), 
      } 
     }, 
     new Predicate<String>() { 
      @Override 
      public boolean test(String name) { 
       return Objects.equals(name, abbrToFind); 
      } 
     }); 
}