1.8 浏览继承层次
George 的团队使用 setObjectColor 方法一段时间后,同事 Martha 发现,该方法找不到组件中 继承 的 setColor 方法,检查继承层次之后,发现在该组件中,setColor 方法是继承自父类的,而且是 protected 方法,所以下面这行代码无法查找到:
Method m = obj.getClass().getMethod("setColor", new Class[] { color.class });
George 决定创建一个工具方法,该方法可以查找 所有访问级别(public protected private package) 的方法,无论该方法是 自身声明 还是 继承 而来的。
可当前 Class 类没有实现该功能的方法,现有的类似方法如下:
getMethod/getMethods- 查找所有
public方法。 - 自身声明 + 继承 的方法。
- 查找所有
getDeclaredMethod/getDeclaredMethods- 查找所有访问级别方法,包含
publicprotectedprivatepackage。 - 仅 自身声明 的方法。
- 查找所有访问级别方法,包含
所以 George 实现一个 getSupportedMethod 方法,以实现该功能:
public static Method getSupportedMethod(Class cls, String name, Class[] paramType)
throws NoSuchMethodException {
if (cls == null)
throw new NoSuchMethodException();
try {
m = cls.getDeclaredMethod(name, paramType);
} catch (NoSuchMethodException e) {
// 递归
return getSupportedMethod(cls.getSuperclass(), name, paramType);
} catch (SecurityException e) {
e.printStackTrace();
}
return m;
}
getSupportedMethod 递归遍历整个继承层次查找给定 签名 的方法:
- 若
cls有父类,则cls.getSupperClass()返回父类Class对象,递归遍历父类。 - 若
cls没有父类,则cls.getSupperClass()返回Object对象,进行最后一次遍历。 - 若
cls是Object,则cls.getSupperClass()返回null。 - 若
cls是null,getSupportedMethod抛出异常,结束。
使用 getSupportedMethod 重写 setObjectColor 方法:
public static void setObjectColor(Object obj, Color color) {
Class cls = obj.getClass();
try {
// 使用 getSupportedMethod 替代 Class.getMethod 方法
Method method = getSupportedMethod(cls, "setColor", new Class[] { Color.class });
method.invoke(obj, new Color[] { color });
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
现在 setObjectColor 方法可以访问所有访问级别(public protected private package)的方法,无论是继承还是自身声明的。
注意
虽然 getSupportedMethod 可以访问所有方法,但不保证有所有方法的 访问权限,若没有访问权限,抛出 IllegalAccessException,第二章将讲解如何传递 可见性检查 以解决该问题。