Я хочу получить все методы класса, включая общедоступные, защищенные, пакетные и частные методы и включая унаследованные методы.
Помните:
-
Class.getDeclaredMethods()
становится общедоступным, защищенным, пакетным и частным методы , но исключает унаследованные методы. -
Class.getMethods
получает унаследованные методы, , но только публичные.
До Java 8 мы могли бы что-то сделать в соответствии с:
Collection<Method> found = new ArrayList<Method>();
while (clazz != null) {
for (Method m1 : clazz.getDeclaredMethods()) {
boolean overridden = false;
for (Method m2 : found) {
if (m2.getName().equals(m1.getName())
&& Arrays.deepEquals(m1.getParameterTypes(), m2
.getParameterTypes())) {
overridden = true;
break;
}
}
if (!overridden) found.add(m1);
}
clazz = clazz.getSuperclass();
}
return found;
Но теперь, если класс реализует некоторый интерфейс с стандартными методами, которые не переопределяются конкретными суперклассами, эти методы избегают описанного выше обнаружения. Кроме того, в настоящее время существуют правила, касающиеся методов по умолчанию с тем же именем, и эти правила также должны быть приняты во внимание.
Вопрос: Каков текущий рекомендуемый способ получения всех методов класса:
Наиболее распространенным определением "все" должны быть методы, к которым можно напрямую обращаться внутри метода экземпляра класса, без использования super
или имен классов:
- Включить общедоступные, защищенные, пакетные и частные методы, объявленные в самом классе.
- Включить защищенные методы своих суперклассов.
- Включить методы пакета своих суперклассов того же пакета.
- Включить методы по умолчанию для своих интерфейсов (те, которые не переопределены/скрыты, см. здесь и здесь).
- Включить статические методы (класс и суперклассы) с соответствующей доступностью.
- Не включайте частные методы суперклассов.
- Не включать переопределенные методы.
- Не включайте скрытые методы (в специальные, не включайте скрытые статические методы).
- Не включать синтетические/мостовые методы.
- Не включать методы, не разрешенные Java, даже если JVM позволяет им.
Итак, указанное выше определение соответствует следующей сигнатуре, когда оба булевых флага false
:
public Collection<Method> getAllMethods(Class clazz,
boolean includeAllPackageAndPrivateMethodsOfSuperclasses,
boolean includeOverridenAndHidden)
Идеальный канонический ответ должен учитывать эти булевы флаги.