Рефлексивные вызовы не работают из-за getClass()

Я столкнулся с чем-то, что я не думаю, что это разрешимо, но это стоит попробовать. Предположим, у вас есть следующие классы:

package a;

public class A
{
    protected A() {}

    public static void staticMethod(A a) {
        // ...
    }
}

public class B extends A
{
    public B() {}
}

Таким образом, вы можете создать экземпляр B из других пакетов, но не A, Теперь предположим, что вы хотите использовать Class.getMethod, только вы используете какую-то структуру рефлексивности, которая выглядит примерно так:

public Object callStaticMethod(Class c, String methodname, Object[] args)
{
    Class[] signature = new Class[args.length];
    for (i = 0 ; i < args.length ; ++i) {
        signature[i] = args.getClass();
    }
    Method m = c.getMethod("methodname", signature);
    return m.invoke(null, args)
}

Этот метод дан мне как есть, и, к сожалению, я не могу его улучшить. Теперь вы можете вызвать метод следующим образом:

package b;

B b;
callStaticMethod(A.class, "staticMethod", b);

... за исключением того, что не будет работать, потому что подпись сгенерирована (на основе getClass() результаты будут {B.class}и нет метода с именем staticMethod в A который занимает B в качестве параметра.

Кто-нибудь из вас знает об этом?

БОНУС: В качестве дополнительной проблемы, есть ли способ, с помощью этого метода, вызвать staticMethod с нулевым параметром (который также может быть вполне допустимым, семантически)? Я лично не нашел способ.

1 ответ

Решение

Что вам нужно сделать, это использовать что-то вроде Class.getMethods, затем проверьте каждый метод-кандидат на пригодность. Вы можете рассмотреть:

  • Бокс (так long.class будет действительным для Long значение в args)
  • Varargs (так что если у вас есть два String аргументы, вы можете считать это действительным для метода foo(String... args))
  • Нулевая совместимость (в основном с любым параметром типа класса)
  • Совместимость назначений (возможно, через Class.isAssignableFrom)
  • Обобщения (это почти наверняка окажется ужасным)

Если существует несколько подходящих методов-кандидатов, вы можете подумать об эмуляции правил перегрузки Java - но я бы, вероятно, избежал этого и пошел бы на ура, если сможете:)

Другие вопросы по тегам