samedi 17 octobre 2020

Is there a better (more safe) way to get the class of the parameterized type?

I want to create a method that returns the class of parameterized type.

private static interface MyInterface<T> {
    void run(T parameter);
}

And one implementation:

private static class MyInterfaceImplString implements MyInterface<String> {
    @Override
    public void run(String parameter) {     }
}

Now, I want the method to return String.class.

I am printing things around, and I can see the information be there but I am just unable to get it. Or at least with a safer way.

public class TypesTest {

    public static void main(String[] args) {
        Class<?> genericParameter1 = getGenericParamaterType(MyInterfaceImplVoid.class);
        System.out.println(genericParameter1); //expect Void here

        Class<?> genericParameter2 = getGenericParamaterType(MyInterfaceImplString.class);
        System.out.println(genericParameter2); //expect String here
    }

    private static Class<?> getGenericParamaterType(Class<? extends MyInterface<?>> clazz) {
        for (Method m : clazz.getMethods()) {
            if ("run".equals(m.getName()) && m.getParameterCount() == 1) {
                System.out.println(TypeLiteral.get(clazz).getParameterTypes(m));
            }
        }

        return null;
    }

    private static class MyInterfaceImplVoid implements MyInterface<Void> {

        @Override
        public void run(Void parameter) {

        }

    }

    private static class MyInterfaceImplString implements MyInterface<String> {

        @Override
        public void run(String parameter) {
        }

    }

    private static interface MyInterface<T> {
        void run(T parameter);
    }
}

Ignore the null return value in the method. I just want to print things, see what I get and then return it. However, my current implementation seems kinda unorthodox, because the class might have more than one run methods that don't refer to MyInterface.

In case of a XY problem, I want be to able to recognize which of these interfaces contain a parameterized type that extends Employee (let's say). I call the run method of the interface indirectly given an HourlyPaidEmployee or a MonthlyPaidEmployee. So, if the underlying implementation is MyInterface<Employee>, I can inject my actual employee (either is monthly or hourly paid). But if the implementation is MyInterface<HourlyEmployee>, I cannot inject a monthly paid one. So, getting the class of the parameterized type, helps me know what types of Employees I can inject safely to run method.

I am with java-8 and Guice dependency in classpath, which contains guava dependency.





Aucun commentaire:

Enregistrer un commentaire