[Java] Dynamic method call by reflection of enum (enum)

Introduction

It's a system repair job, but it's been a while since Java. The environment is Java 7.

FugaName1 to FugaName4 in a certain table column will be expanded to FugaName1 to FugaName50. I suggested that if you want to increase it to that extent, it would be better to use a separate table, but considering the usage situation, it is not necessary to separate the tables.

Before renovation

The following Enum class was created to output to a file. The constructor was added on 2017/06/11.

Enum class


public class Hoge {
    public String no;
    public String fuganame1;
    public String fuganame2;
    public String fuganame3;
    public String fuganame4;
 
    //constructor
    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;   //Physical name
        private final String colNameLogical;    //Logical name
        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;
        }
    }
 }

Since it is about four, it is written solidly.

Where to use


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);

Experiment

If it's still four, it's acceptable even if it's solid, but I don't think it's cool as a programmer to write 50, and it seems that there are several other people doing the same thing, so in the future Thinking about that, I tried reflection. This is my first time to use reflection, so I will make a confirmation program.

Experiment


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); //result: Fuga Name2
    }
}

After renovation

For the Enum class, I increased it to 50 for the time being. Regarding the place of use, it corresponded by reflection.

Where to use


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 2017/06/11

I received a comment from Mr. saka1029 and learned how to prevent reflection.

Where to use


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);
}

At the constructor, getField (field name) is used to get the field variable. In that case, throws IllegalArgumentException, IllegalAccessException will be added.

See also: Differences between getFields and getDeclaredFields

Enum class


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

        //Same thing as below FugaName1-Do up to 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()));
        }
    }

Looking at the Java API specification, there was a statement that the order was certainly not fixed. Class#getFields()

Returns an array holding a Field object that reflects all accessible public fields of the class or interface represented by this Class object. The elements in the returned array are never sorted or in any particular order.

Since it is not possible to acquire field information in the order in which fields are defined with standard Java functions, the order is specified by using annotations. Reference: Print fields in order of annotation value

Finally

It's my first time to do a full-scale renovation work in Java, so there may actually be a better way.

reference

Recommended Posts

[Java] Dynamic method call by reflection of enum (enum)
[Java] [Kotlin] Generically call valueOf and values of Enum
Benefits of Java static method
Summary of values returned by the Spliterator characteristics method #java
Screen transition by Post method [Java]
[Java] Output by FormatStyle of DateTimeFormatter
Call the super method in Java
Implementation of clone method for Java Record
Java method
java (method)
Rails enum Select prefecture by pull-down method
Call Java method from JavaScript executed in Java
Consider searching Java Enum by another element
[Java] enum
Java method
[Java] method
[Java] method
Call a method of the parent class by explicitly specifying the name in Ruby
[Android] Call Kotlin's default argument method from Java
[Java] Handling of JavaBeans in the method chain
The order of Java method modifiers is fixed
Java method call from RPG (method call in own class)
Method name of static factory method learned from Java 8
Accuracy of pi calculation by Monte Carlo method
[Note] Java: Speed of List processing by purpose
About call timing and arguments of addToBackStack method
Method name of method chain in Java Builder + α
Replacing system environment variables by reflection in java
Provisional memo when the name of the method parameter of the Java class cannot be obtained by reflection in the Eclipse plug-in project.
[Java] Integer information of characters in a text file acquired by the read () method
Java8 method reference
Java Dynamic Proxy
[Java] forEach method
[Java] Lambda Metafactory speeds up function calls by reflection to the direct call level
java8 method reference
[Java] Random method
[Java] Overview of Java
[Java] split method
[Java] Basic summary of Java not covered by Progate ~ Part 1 ~
[Java] How to use compareTo method of Date class
How to call functions in bulk with Java reflection
I want to call a method of another class
[Kotlin] Get the argument name of the constructor by reflection
Summary of revisions (new era) support by Java version
Call a method with a Kotlin callback block from Java
Comparative study of TLS Cipher Suite supported by Java 8
I want to call the main method using reflection
Summary of file reading method for each Java file format