[Java] Appel de méthode dynamique par réflexion du type enum (enum)

introduction

C'est un travail de réparation de système, mais cela fait longtemps que Java. L'environnement est Java 7.

FugaName1 à FugaName4 dans une certaine colonne de table sera développé en FugaName1 à FugaName50. J'ai suggéré que si vous voulez l'augmenter dans cette mesure, il serait préférable d'utiliser un tableau séparé, mais compte tenu de la situation d'utilisation, il n'est pas nécessaire de séparer les tableaux.

Avant rénovation

La classe Enum suivante a été créée pour sortir dans un fichier. Ajouté le constructeur le 2017/06/11.

Classe Enum


public class Hoge {
    public String no;
    public String fuganame1;
    public String fuganame2;
    public String fuganame3;
    public String fuganame4;
 
    //constructeur
    public Hoge(String _no, HashMap<String, String> resultList) {
        no = _no;
        fuganame1 = resultList.get(dataParams.FugaName1.getColNamePhysical());   
        fuganame2 = resultList.get(dataParams.FugaName2.getColNamePhysical());   
        fuganame3 = resultList.get(dataParams.FugaName3.getColNamePhysical());   
        fuganame4 = resultList.get(dataParams.FugaName4.getColNamePhysical());   
    }

    public enum dataParams{
          No         ("no"        , "No"         , 0)
        , FugaName1  ("fuganame1" , "Fuga Name1" , 1)
        , FugaName2  ("fuganame2" , "Fuga Name2" , 2)
        , FugaName3  ("fuganame3" , "Fuga Name3" , 3)
        , FugaName4  ("fuganame4" , "Fuga Name4" , 4);

        private final String colNamePhysical;   //Nom physique
        private final String colNameLogical;    //Nom logique
        private final int colIdx;

        private dataParams( String physical , String logical, int index) {
            colNamePhysical = physical;
            colNameLogical = logical;
            colIdx = index;
        }

        public String getColNamePhysical() {
            return colNamePhysical;
        }
        public String getColNameLogical() {
            return colNameLogical;
        }
        public int getColIdx() {
            return colIdx;
        }
    }
 }

Puisqu'il est environ quatre, il est écrit solidement.

Où utiliser


String fugaName1 = (String)Hoge.dataParams.FugaName1.getColNamePhysical();
addMap.put(fmColumnName, fugaName1);
resultList.add(addMap);
String fugaName2 = (String)Hoge.dataParams.FugaName2.getColNamePhysical();
addMap.put(fmColumnName, fugaName2);
resultList.add(addMap);
String fugaName3 = (String)Hoge.dataParams.FugaName3.getColNamePhysical();
addMap.put(fmColumnName, fugaName3);
resultList.add(addMap);
String fugaName4 = (String)Hoge.dataParams.FugaName4.getColNamePhysical();
addMap.put(fmColumnName, fugaName4);
resultList.add(addMap);

Expérience

Si c'est encore quatre, c'est acceptable même si c'est solide, mais je pense qu'écrire 50 n'est pas bon en tant que programmeur, et il semble qu'il y ait plusieurs autres choses qui font la même chose, donc à l'avenir En y réfléchissant, j'ai essayé la réflexion. C'est la première fois que j'utilise la réflexion, je vais donc créer un programme de confirmation.

Expérience


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String []args) {

        Enum<?> clz = Enum.valueOf(Hoge.dataParams.class, "FugaName2");
        Object[] consts = clz.getClass().getEnumConstants();
        Class<?> sub = consts[0].getClass();
        Method mth = sub.getDeclaredMethod("getColNameLogical"); //getColNamePhysical");
        String val = (String) mth.invoke(consts[clz.ordinal()]);

        System.out.println(val); //résultat: Fuga Name2
    }
}

Après rénovation

Pour la classe Enum, je l'ai augmenté à 50 pour le moment. Le lieu d'utilisation était reflété.

Où utiliser


Class<?> clz = Hoge.dataParams.class;
Object[] consts = clz.getEnumConstants();
Class<?> sub = consts[0].getClass();

try {
    Method mth = sub.getDeclaredMethod("getColNamePhysical");
    for(int i=1; i<=50; i++){
        Enum<?> v = Enum.valueOf(Hoge.dataParams.class, String.format("FugaName%d", i));
        String fugaName = (String) mth.invoke(consts[v.ordinal()]);
        addMap.put(fmColumnName, fugaName);
        resultList.add(addMap);
    }
} catch (NoSuchMethodException|SecurityException|IllegalAccessException|InvocationTargetException ex) {
    throw ex;
}

Postscript 11/06/2017

J'ai reçu un commentaire de M. saka1029 et j'ai appris comment empêcher la réflexion.

Où utiliser


for (Hoge.dataParams v : Hoge.dataParams.values()) {
    if (!v.toString().matches("FugaName\\d+"))
        continue;
    String fugaName = v.getColNamePhysical();
    addMap.put(fmColumnName, fugaName);
    resultList.add(addMap);
}

Au niveau du constructeur, getField (nom de champ) est utilisé pour obtenir les variables de champ. Dans ce cas, lève IllegalArgumentException, IllegalAccessException sera ajouté.

Voir aussi: Différences entre getFields et getDeclaredFields

Classe Enum


    //constructeur
    public Hoge(String _no, HashMap<String, String> resultList) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        no = _no;

        //Même chose que ci-dessous FugaName1-Faites jusqu'à 50
        // fuganame1 = resultList.get(dataParams.FugaName1.getColNamePhysical());
        for (Hoge.dataParams v : Hoge.dataParams.values()) {
            String name = v.toString();
            if (!name.matches("FugaName\\d+"))
                continue;
            Field field = this.getClass().getField(name.toLowerCase());
            field.set(this, resultList.get(v.getColNamePhysical()));
        }
    }

En regardant la spécification de l'API Java, il y avait une description que l'ordre n'était certainement pas corrigé. Class#getFields()

Renvoie un tableau contenant un objet Field qui reflète tous les champs publics accessibles de la classe ou de l'interface représentée par cet objet Class. Les éléments du tableau renvoyé ne sont jamais triés ni dans un ordre particulier.

Puisqu'il n'est pas possible d'acquérir des informations de champ dans l'ordre dans lequel les champs sont définis avec les fonctions Java standard, l'ordre est spécifié à l'aide d'annotations. Voir aussi: Champs de sortie par ordre de valeur d'annotation (http://java-beginner.com/practice-print-fields-in-order/)

finalement

C'est la première fois que je travaille sérieusement sur Java, il existe donc peut-être un meilleur moyen.

référence

Recommended Posts

[Java] Appel de méthode dynamique par réflexion du type enum (enum)
[Java] [Kotlin] Appeler valueOf et les valeurs de Enum de manière générique
Avantages de la méthode statique Java
Récapitulatif des valeurs renvoyées par la méthode des caractéristiques Spliterator #java
Transition d'écran par méthode Post [Java]
[Java] DateTimeFormatter sortie par FormatStyle
Appelez la super méthode en Java
Implémentation de la méthode de clonage pour Java Record
Méthode Java
java (méthode)
Rails enum Sélectionnez la préfecture par méthode déroulante
Appel de méthodes Java à partir de JavaScript exécutées en Java
Envisagez de rechercher Java Enum par un autre élément
[Java] enum (type d'énumération)
Méthode Java
[Java] méthode
[Java] méthode
Nommer et appeler explicitement des méthodes de classe parent dans Ruby
[Android] Appeler la méthode d'argument par défaut de Kotlin depuis Java
[Java] Gestion des Java Beans dans la chaîne de méthodes
L'ordre des modificateurs de méthode Java est fixe
Appel de méthode Java depuis RPG (appel de méthode dans sa propre classe)
Nom de la méthode de la méthode de fabrique statique apprise à partir de Java 8
Précision du calcul du ratio de circonférence par la méthode de Monte Carlo
[Note] Java: vitesse de traitement de la liste par objectif
À propos de la synchronisation des appels et des arguments de la méthode addToBackStack
Nom de méthode de la chaîne de méthodes dans Java Builder + α
Remplacement des variables d'environnement système par réflexion en Java
Mémo de support temporaire lorsque le nom du paramètre de méthode de la classe Java ne peut pas être obtenu par réflexion dans le projet de plug-in Eclipse
[Java] Informations entières des caractères du fichier texte acquises par la méthode read ()
Référence de la méthode Java8
Proxy dynamique Java
[Java] méthode forEach
référence de la méthode java8
[Java] Méthode aléatoire
[Java] Présentation de Java
[Java] méthode de fractionnement
[Java] Résumé de base de Java non couvert par Progate ~ Partie 1 ~
Comment appeler des fonctions en bloc avec la réflexion Java
Je veux appeler une méthode d'une autre classe
[Kotlin] Récupère le nom de l'argument du constructeur par réflexion
Résumé des révisions (nouveaux problèmes de yuan) par version Java
Appeler une méthode avec le bloc de rappel de Kotlin depuis Java
Etude comparative de TLS Cipher Suite pris en charge par Java 8
Je veux appeler la méthode principale en utilisant la réflexion
Résumé des méthodes de lecture de fichiers pour chaque format de fichier Java