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
    • 查找所有访问级别方法,包含 public protected private package
    • 自身声明 的方法。

所以 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 递归遍历整个继承层次查找给定 签名 的方法:

  1. cls 有父类,则 cls.getSupperClass() 返回父类 Class 对象,递归遍历父类。
  2. cls 没有父类,则 cls.getSupperClass() 返回 Object 对象,进行最后一次遍历。
  3. clsObject,则 cls.getSupperClass() 返回 null
  4. clsnullgetSupportedMethod 抛出异常,结束。

使用 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,第二章将讲解如何传递 可见性检查 以解决该问题。

results matching ""

    No results matching ""