You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8反射:如何获取方法的最高声明类或接口?

问题:获取Java方法的最高声明类/接口

我需要在Java 8中获取方法的最高声明类或接口。示例如下:

package pkg;

public class Classes {

    public static interface IInterface {
        void iMethod();
    }

    public abstract static class AClass implements IInterface {
        protected abstract void aMethod();
    }

    public static class SubClass extends AClass {
        
        @Override
        public void iMethod() {
            System.out.println("Sub iMethod");
        }

        @Override
        protected void aMethod() {
            System.out.println("Sub aMethod");
        }
    }
}
// 预期结果:
// getFirstDeclarator(Classes.SubClass.class, iMethod) -> AClass
// getFirstDeclarator(Classes.SubClass.class, aMethod) -> IInterface

我自己实现的代码仅对public方法有效,因为Class#getMethod仅支持可访问方法,我需要让它同样适用于private/protected方法,请问有可行方案吗?

我的现有代码:

import pkg.Classes;

import java.lang.reflect.Method;

public class Main {

    public static void main(String[] args) throws Exception {

        Method iMethod = Classes.SubClass.class.getDeclaredMethod("iMethod");
        Method aMethod = Classes.SubClass.class.getDeclaredMethod("aMethod");
        System.out.println(getFirstDeclarator(Classes.SubClass.class, iMethod));
        System.out.println(getFirstDeclarator(Classes.SubClass.class, aMethod));

    }

    /**
     * 获取方法的声明类或接口。如果方法被重写,返回声明该方法的最高父类或接口。
     */
    public static Class<?> getFirstDeclarator(Class<?> startClass, Method method) {

        Class<?> superClass = startClass.getSuperclass();
        if (superClass != null) {
            try {
                // 问题所在:Class#getMethod 仅适用于可访问方法
                superClass.getMethod(method.getName(), method.getParameterTypes());
                return getFirstDeclarator(superClass, method);
            } catch (NoSuchMethodException e) {
                // 父类中未声明该方法
            }
        }

        for (Class<?> iface : startClass.getInterfaces()) {
            try {
                iface.getMethod(method.getName(), method.getParameterTypes()); // 同样的问题
                return getFirstDeclarator(iface, method);
            } catch (NoSuchMethodException e) {
                // 接口中未声明该方法
            }
        }

        return startClass;
    }
}

解决方案

问题核心在于Class#getMethod只会查找public方法(包括继承来的),无法处理protected/private方法。要解决这个问题,我们需要改用Class#getDeclaredMethod获取当前类声明的所有方法(无论访问修饰符),同时判断该方法是否属于可被重写的范畴(private方法无法被重写,无需追踪)。

修改后的实现代码如下:

import pkg.Classes;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Main {

    public static void main(String[] args) throws Exception {
        Method iMethod = Classes.SubClass.class.getDeclaredMethod("iMethod");
        Method aMethod = Classes.SubClass.class.getDeclaredMethod("aMethod");
        System.out.println(getFirstDeclarator(Classes.SubClass.class, iMethod)); // 输出 class pkg.Classes$AClass
        System.out.println(getFirstDeclarator(Classes.SubClass.class, aMethod)); // 输出 interface pkg.Classes$IInterface
    }

    /**
     * 获取方法的最高声明类或接口。如果方法被重写,返回声明该方法的最顶层父类/接口。
     */
    public static Class<?> getFirstDeclarator(Class<?> startClass, Method method) {
        // 先处理父类链
        Class<?> superClass = startClass.getSuperclass();
        if (superClass != null && !Object.class.equals(superClass)) {
            try {
                // 获取父类中直接声明的同名同参数方法
                Method superMethod = superClass.getDeclaredMethod(method.getName(), method.getParameterTypes());
                // 排除private方法(无法被重写)
                if (!Modifier.isPrivate(superMethod.getModifiers())) {
                    return getFirstDeclarator(superClass, method);
                }
            } catch (NoSuchMethodException e) {
                // 父类无对应方法,跳过
            }
        }

        // 再处理接口链
        for (Class<?> iface : startClass.getInterfaces()) {
            try {
                // 接口方法默认都是public,直接用getMethod查找
                iface.getMethod(method.getName(), method.getParameterTypes());
                return getFirstDeclarator(iface, method);
            } catch (NoSuchMethodException e) {
                // 接口无对应方法,跳过
            }
        }

        // 无更高层声明,返回当前类
        return startClass;
    }
}

关键修改说明

  1. 父类处理:用getDeclaredMethod替代getMethod,获取父类所有直接声明的方法,同时通过Modifier.isPrivate排除无法被重写的private方法。
  2. 终止条件:父类遍历到Object.class时停止,避免无意义递归。
  3. 接口处理:接口方法均为public,保留getMethod逻辑即可,无需额外修改。

修改后,无论是protected还是public方法,都能正确找到其最高层的声明类/接口。

内容的提问来源于stack exchange,提问作者crazycat256

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 12:44:57