Если вы вообще не хотите (или не можете) изменить определение классов A
, B
и C
, то наиболее вероятный вариант, который у вас есть, - это вызвать метод с помощью отражения..
В настоящее время статическая типизация Java не может гарантировать, что элементы внутри list
имеют a getName()
метод - потому что все, что он может гарантировать, это то, что они являются экземплярами java.lang.Object
.
Даже ваш состав не помогает, потому что вы страдаете от той же самой проблемы с вашим массивом classes
.Обратите внимание, что Class<E>
на самом деле является общим, с параметром типа, соответствующим фактическому классу, в который будет выполняться приведение.Поскольку элементы массива просто имеют необработанный тип Class
(примерно эквивалентный Class<? extends Object>
), результат вызова classes[i].cast()
является, опять же, экземпляром java.lang.Object
.И поэтому вы не можете вызвать getName
для него.
Если не существует какого-либо общего суперинтерфейса этих трех классов, который определяет getName()
, вы не сможете удовлетворить компилятор, что этодопустимый метод для вызова их в этом стиле.
Один очень простой способ обойти это просто обработать каждый класс по-разному - использовать проверки instanceof
и затем явно привести к A
, B
или C
.Это сделало бы компилятор счастливым и обеспечило бы некоторую статическую проверку типов (например, если метод был переименован в A
, ваш код перестал бы компилироваться), но утроил бы объем кода, который вам пришлось бы писать, и запускаетриск того, что вы пропустите новый класс D
позже.
Другой вариант - отражение - возьмите метод getName
непосредственно от объектов во время выполнения и вызовите его:
for(int i = 0; i < list.length;i++)
{
final Object obj = list.get(i);
final Method m = obj.getClass.getMethod("getName"); //A,B,and C have method getName() in common
m.invoke(obj);
// Exception-handling code omitted
}
Это «просто работает», но плохо сказывается на производительности, а также означает, что любые изменения в ваших классах не будут приниматься до тех пор, пока вы не получите NoSuchMethodException
во время выполнения.
Лучшее решение на самом делеввести интерфейс и изменить классы.