Рефлексивные вызовы не работают из-за 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 - но я бы, вероятно, избежал этого и пошел бы на ура, если сможете:)