mercredi 1 mai 2019

Generic parameters that are interfaces and classes via instance reflection

I am trying to implement the a class in Java with a generic type parameter E. Within this class I have a method that enables the passing in of a Method object that I perform operations with later. This Method, as I intend to use it, is supposed to accept two arguments, both of which are supposed to be E. Thus, when the Method is passed in, I would like to check that its parameters match expectations, and throw an exceptions if not. However, since I know of no way to check get E's runtime class directly, I have the constructor accept an object of type E as an example, and use this to create a Class object, which I then use for comparison. However, this idea breaks down when E is an interface or an abstract class because there is no longer a possible way to pass in an immediate instance of E, and all parameter type checking will now revolve around this subclass/implementing class. Is there a good way around this issue?

Here are the relevant sections of code:

public abstract class DataStructure<E>
{
    ...
    private Method method;
    protected final Class<?> ex;

    protected DataStructure(E example)
    {
    ...
    ex = example.getClass();
        method = null;
    }

    ...

    public void setModificationMethod(Method m)
    {
    Class<?>[] needed = new Class<?>[] {ex, ex};
    Class<?>[] given = m.getParameterTypes();
    if(given.length != needed.length)
    {
    throw new IllegalArgumentException("Invalid method.");
    }
    for(int i = 0; i < needed.length; i++)
    {
    if(!given[i].isAssignableFrom(needed[i]))
    {
        throw new IllegalArgumentException("Invalid method.");
    }
    }
    if(!Modifier.isStatic(m.getModifiers()))
    {
        throw new IllegalArgumentException("Non-static methods must also pass in an instance to use.");
    }
    method = m;
    }
    ...

    protected void modify(E presentData, E newData) throws ReflectiveOperationException
    {
        method.setAccessible(true);

            ...

            //after making sure that preconditions are met and that there is a method to call
            method.invoke(null, presentData, newData);
            method.setAccessible(false);
    }
}

I also handle the case where the method is an instance method, but that code is mostly redundant and irrelevant to my question, so it has been omitted.

Additionally, if there are any noticeable errors in my code, I would appreciate comments pointing them out. I am new to reflection as a whole and am still learning how to use it.





Aucun commentaire:

Enregistrer un commentaire