DeclaredMethod

java #反射

java反射使用getDeclaredMethods

最近在使用getDeclaredMethods方法获取类中的方法时碰到奇怪的问题,先来看看getDeclaredMethods方法的注释:

/** * * Returns an array containing {@code Method} objects reflecting all the * declared methods of the class or interface represented by this {@code * Class} object, including public, protected, default (package) * access, and private methods, but excluding inherited methods. * * <p> If this {@code Class} object represents a type that has multiple * declared methods with the same name and parameter types, but different * return types, then the returned array has a {@code Method} object for * each such method. * * <p> If this {@code Class} object represents a type that has a class * initialization method {@code <clinit>}, then the returned array does * <em>not</em> have a corresponding {@code Method} object. * * <p> If this {@code Class} object represents a class or interface with no * declared methods, then the returned array has length 0. * * <p> If this {@code Class} object represents an array type, a primitive * type, or void, then the returned array has length 0. * * <p> The elements in the returned array are not sorted and are not in any * particular order. * * @return the array of {@code Method} objects representing all the * declared methods of this class * @throws SecurityException * If a security manager, <i>s</i>, is present and any of the * following conditions is met: * * <ul> * * <li> the caller's class loader is not the same as the * class loader of this class and invocation of * {@link SecurityManager#checkPermission * s.checkPermission} method with * {@code RuntimePermission("accessDeclaredMembers")} * denies access to the declared methods within this class * * <li> the caller's class loader is not the same as or an * ancestor of the class loader for the current class and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to the package * of this class * * </ul> * * @jls 8.2 Class Members * @jls 8.4 Method Declarations * @since JDK1.1 * 1.返回一个包含Method对象的数组,该对象反映了此Class对象表示的类或接口的所有声明方法,包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法。 * 2.如果此Class对象表示一个类型,该类型具有多个具有相同名称和参数类型但返回类型不同的声明方法,则 返回的数组对于每个此类方法都有一个Method对象。 * 3.如果此Class对象表示具有类初始化方法的类型<clinit>则 返回的阵列不具有相应的Method的对象。(不返回构造参数) * 4.如果此Class对象表示没有声明方法的类或接口,则返回的数组长度为 0。 * 5.如果此Class对象表示数组类型、基本类型或 void,则返回的数组长度为 0。 * 6.返回的数组中的元素没有排序,也没有任何特定的顺序。 * 返回: * 表示此类的所有声明方法的Method对象数组 * 抛出: * SecurityException – 如果存在安全管理器s并且满足以下任何条件: * 调用者的类加载器与此类的类加载器不同,并且使用RuntimePermission("accessDeclaredMembers")调用s.checkPermission方法拒绝访问此类中的声明方法 * 调用者的类加载器与当前类的类加载器不同,或者不是该类加载器的祖先,并且调用s.checkPackageAccess()拒绝访问此类的包 * 自从:JDK1.1 * 外部注释:@org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Contract(pure = true) */ @CallerSensitive public Method[] getDeclaredMethods() throws SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyMethods(privateGetDeclaredMethods(false)); }

顺序问题

在JDK的API文档里明确标注了(第6点):不能保证getDeclaredFields()/getDeclaredMethods()返回的Fields[] 和 Methods[] 的顺序。注意是不能保证返回顺序,而不是返回是乱序:它完全可能是乱序,也还可能是按照声明顺序排布。

这是因为,JVM有权在编译时,自行决定类成员的顺序,不一定要按照代码中的声明顺序来进行编译。因此返回的顺序其实是class文件中的成员正向顺序,只不过在编译时这个顺序不一定等于声明时的顺序。

额外方法问题

JDK文档标明的第一点说不包括继承方法,但是在实际使用中,还是会发现有包含父类方法的情况,下面用案例展示

  • 正常例子

    public class { class A { void add(Object obj) { } } class B extends A{ void add(Object obj) { } } public static void main(String[] args) { for (Method method : B.class.getDeclaredMethods()) { System.out.println(method.toString()); } } }

    这里执行结果为

    void com.demo.service.rights.domain.C$B.add(java.lang.Object)

    正常的只获取了子类中的methon

  • 非正常例子

    public class C{ class A<T> { void add(T t) { } } class B extends A<String>{ void add(String obj) { } } public static void main(String[] args) { for (Method method : B.class.getDeclaredMethods()) { System.out.println(method.toString()); } } }

    这里执行结果为

    void com.demo.member.service.rights.domain.C$B.add(java.lang.String) void com.demo.member.service.rights.domain.C$B.add(java.lang.Object)

    发现把父类的方法也给查出来了

  • 解决办法

    手动判断method.isBridge()来判断是不是继承了父类的方法的method

总结

使用反射的方法的时候,需要注意下对应api上面的描述,不然写了bug都不自知


__EOF__

本文作者我在清水河边
本文链接https://www.cnblogs.com/wzqshb/p/17703906.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   _我在清水河边  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示