2013-11-17 2 views
2

Можно ли вызвать метод, в котором объект аргумента или класс аргумента является подклассом, и сам метод взял суперкласс в качестве аргумента?Вызов getMethod с подклассом как аргумент метода

Я пытаюсь вызвать этот метод public void setNewProblem(Problem problem); с конкретной реализацией абстрактного класса Проблема. К сожалению, я получаю исключение NoSuchMethodException.

Я называю ВЫЗОВ так:

Method method = model.getClass().getMethod("set" + propertyName, new Class[] { newValue.getClass() }); 
method.invoke(model, newValue); 

Если изменить newValue.getClass() на Problem.class все работает отлично. Любая идея, как передать подкласс public void setNewProblem(Problem problem);?

+2

Исключение не вызвано invoke(). Это вызвано getMethod(). Вам нужен фактический объявленный класс, чтобы найти метод в классе. Но при вызове метода вы можете передать любой экземпляр подкласса. Почти каждый раз, когда используется отражение, оно не должно. Вероятно, есть лучший способ добиться того, чего вы хотите, чем отражения. Чего вы хотите достичь? –

+0

Да, исключение вызвано getMethod(), возможно, я был неясен там. Я использую [this] (http://www.oracle.com/technetwork/articles/javase/index-142890.html) реализацию MVC.В этой реализации контроллер использует invoke, чтобы сообщить модели, что изменилось в представлении. – hofmeister

ответ

3

Вы должны запросить точный тип. Это связано с тем, что у вас может быть несколько возможных перегруженных методов, и вам нужно знать то, что вам нужно.

Таким образом, вы можете ссылаться на подкласс, но вы не можете просить подкласс не быть там.

Что вы можете сделать, это посмотреть на все методы и найти совпадение.

Если вам нужно установить сеттер или геттер для объекта, я предлагаю вам посмотреть BeanIntrospector, в котором вы найдете все свойства и методы getter/setter для этого свойства.

+0

Проблема в том, что я не знаю, какая проблема добавлена ​​в модель. Это могут быть проблемыX, ProblemY или ProblemZ. – hofmeister

+0

@hofmeister Вам не нужно знать, какой тип экземпляра он есть, вам нужно только знать тип метода. –

+0

Да, справа. Задача ProblemX проблемы должна быть достаточной для установки правильных аргументов для getMethod()? – hofmeister

1

Проблема заключается в том, что newValue.getClass() является подклассом класса в объявленном методе.

От Class.getMethod:

Чтобы найти соответствующий метод в классе C: Если C декларирует ровно один открытый метод с указанным именем и точно те же формальные типов параметров, то есть метод отражается.

Вы могли бы работать свой путь вверх по цепочке наследования, пока он не работает:

Method getMethod(Class c1, Class c2) { 
    if(c2.getSuperClass() == null) { 
     return c1.getMethod("set" + propertyName, new Class[] { c2 }); 
    } 
    try { 
     return c1.getMethod("set" + propertyName, new Class[] { c2 }); 
    } catch(NoSuchMethodException e) { 
     return getMethod(c1, c2.getSuperClass()); 
    } 
} 

Использование:

Method method = getMethod(model.getClass(), newValue.getClass()); 

Я затрудняюсь предположить, что это, однако, так как она не покрывает 100% случаев (например, если формальный класс аргументов является интерфейсом), и то, как вы это делаете, плохо.

1

Когда вы звоните Class.getMethod(), вы должны правильно указать формальные типы. Не типы фактических аргументов, которые вы планируете предоставить. Вы должны точно соответствовать тому, что говорится в объявлении соответствующего метода.

"The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order."

Смежные вопросы