即使对于“在 Java 8 之前”的场景,您的代码片段也是不正确的。但是收集所有方法并不是通常的情况,因为您通常需要有关特定上下文的方法,例如,您可能想知道给定上下文可以访问哪些方法,即使您考虑非方法,也不包括所有方法。如果你真的想要所有的方法,你必须记住,方法永远不会被重写,包私有方法只有在在同一个中声明时才会被重写。因此,筛选每个遇到的方法签名是不正确的。publicprivatestaticpackage
更糟糕的是,方法可能会被不同的修饰符覆盖。后者可以通过保持从实际类开始的想法来解决,并用于获取所有方法(包括方法)并遍历超类层次结构,以便已经遇到的覆盖具有限制最少的访问修饰符。Class.getMethods()publicdefaultjava.lang.Object
顺便说一句,嵌套线性搜索循环从来都不是一个好主意。你很快就会得到一个二次或更糟糕的复杂性。
您可以使用以下方法收集方法:
public static Set<Method> getAllMethods(Class<?> cl) {
    Set<Method> methods=new LinkedHashSet<>();
    Collections.addAll(methods, cl.getMethods());
    Map<Object,Set<Package>> types=new HashMap<>();
    final Set<Package> pkgIndependent = Collections.emptySet();
    for(Method m: methods) types.put(methodKey(m), pkgIndependent);
    for(Class<?> current=cl; current!=null; current=current.getSuperclass()) {
        for(Method m: current.getDeclaredMethods()) {
            final int mod = m.getModifiers(),
                access=Modifier.PUBLIC|Modifier.PROTECTED|Modifier.PRIVATE;
            if(!Modifier.isStatic(mod)) switch(mod&access) {
                case Modifier.PUBLIC: continue;
                default:
                    Set<Package> pkg=
                        types.computeIfAbsent(methodKey(m), key -> new HashSet<>());
                    if(pkg!=pkgIndependent && pkg.add(current.getPackage())) break;
                    else continue;
                case Modifier.PROTECTED:
                    if(types.putIfAbsent(methodKey(m), pkgIndependent)!=null) continue;
                    // otherwise fall-through
                case Modifier.PRIVATE:
            }
            methods.add(m);
        }
    }
    return methods;
}
private static Object methodKey(Method m) {
    return Arrays.asList(m.getName(),
        MethodType.methodType(m.getReturnType(), m.getParameterTypes()));
}
但如前所述,它可能不适合你想做的任何事情。您应该首先问自己以下问题:
- 您是否正在寻找构成API的方法(通常也是唯一的)?publicprotected
- 或者你想真正看到某个/上下文可以访问的方法?classpackage
- 是否应包括方法?static
- 是否应包括合成/桥接方法?
- 等。
以下是适合您更具体要求的修订方法:
public static Collection<Method> getAllMethods(Class clazz,
                boolean includeAllPackageAndPrivateMethodsOfSuperclasses,
                boolean includeOverridenAndHidden) {
    Predicate<Method> include = m -> !m.isBridge() && !m.isSynthetic() &&
         Character.isJavaIdentifierStart(m.getName().charAt(0))
      && m.getName().chars().skip(1).allMatch(Character::isJavaIdentifierPart);
    Set<Method> methods = new LinkedHashSet<>();
    Collections.addAll(methods, clazz.getMethods());
    methods.removeIf(include.negate());
    Stream.of(clazz.getDeclaredMethods()).filter(include).forEach(methods::add);
    final int access=Modifier.PUBLIC|Modifier.PROTECTED|Modifier.PRIVATE;
    Package p = clazz.getPackage();
    if(!includeAllPackageAndPrivateMethodsOfSuperclasses) {
        int pass = includeOverridenAndHidden?
            Modifier.PUBLIC|Modifier.PROTECTED: Modifier.PROTECTED;
        include = include.and(m -> { int mod = m.getModifiers();
            return (mod&pass)!=0
                || (mod&access)==0 && m.getDeclaringClass().getPackage()==p;
        });
    }
    if(!includeOverridenAndHidden) {
        Map<Object,Set<Package>> types = new HashMap<>();
        final Set<Package> pkgIndependent = Collections.emptySet();
        for(Method m: methods) {
            int acc=m.getModifiers()&access;
            if(acc==Modifier.PRIVATE) continue;
            if(acc!=0) types.put(methodKey(m), pkgIndependent);
            else types.computeIfAbsent(methodKey(m),x->new HashSet<>()).add(p);
        }
        include = include.and(m -> { int acc = m.getModifiers()&access;
            return acc!=0? acc==Modifier.PRIVATE
                    || types.putIfAbsent(methodKey(m), pkgIndependent)==null:
                noPkgOverride(m, types, pkgIndependent);
        });
    }
    for(clazz=clazz.getSuperclass(); clazz!=null; clazz=clazz.getSuperclass())
        Stream.of(clazz.getDeclaredMethods()).filter(include).forEach(methods::add);
    return methods;
}
static boolean noPkgOverride(
        Method m, Map<Object,Set<Package>> types, Set<Package> pkgIndependent) {
    Set<Package> pkg = types.computeIfAbsent(methodKey(m), key -> new HashSet<>());
    return pkg!=pkgIndependent && pkg.add(m.getDeclaringClass().getPackage());
}
private static Object methodKey(Method m) {
    return Arrays.asList(m.getName(),
        MethodType.methodType(m.getReturnType(), m.getParameterTypes()));
}