如何在运行时调用方法时忽略修饰符 - JAVA

时间:2014-12-31 23:35:30

标签: java oop reflection

我想查找类中每个方法的特定注释,如果找到带有该注释的方法,我想调用它。 此外,如果在当前类中找不到它,则应检查所有继承类。

我的问题是可能有一些受保护的方法,私有等等。我想忽略这些修饰符并获得对所有方法的访问权(即使它是私有的等等)

所以这就是我调用的方式(给出的是我正在寻找的注释的名称:

if (m.isAnnotationPresent(Given.class)) {
        m.invoke(instObj, intArgument);
 }

(这就是我检查类层次结构的其余部分 - 如果我在某个地方犯了错误,请赐教我:

Class<?> superC = c.getSuperclass();
while (!(superC.equals(Object.class))) {
                handleGiven(instObj, superC, methods, currentSentence,
                        methodArgument);

handleGiven是递归调用时。

2 个答案:

答案 0 :(得分:2)

您需要使用getDeclaredMethods来获取所有方法(公共,受保护等),如下所示:

public Method findMethodWithAnnotation(Class<?> clazz,
        Class<? extends Annotation> annotation) {
    for (Method m : clazz.getDeclaredMethods()) {
        if (m.isAnnotationPresent(annotation)) {
            return m;
        }
    }
    return null;
}

并按照以下方式检查:

    Class<?> clazz = ..; //get the class
    Method m = null;
    do {
        m = findMethodWithAnnotation(clazz, DesiredAnnotation.class);
        clazz = clazz.getSuperclass();
    } while (m == null && clazz != null);
    System.out.println(m);

还要确保您的注释具有以下注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

如果您需要字段注释,请查看getDeclaredFields和类似方法。

您需要在调用之前使方法可访问

m.setAccessible(true);

如果您想要更紧凑和递归的实现,可以更改为:

public Method findMethodWithAnnotation(Class<?> clazz,
        Class<? extends Annotation> annotation) {

    if (clazz == Object.class || clazz == null) return null;
    for (Method m : clazz.getDeclaredMethods()) {
        if (m.isAnnotationPresent(annotation)) {
            return m;
        }
    }
    return findMethodWithAnnotation(clazz.getSuperClass(), annotation);
}

使用方法是:

Method m = findMethodWithAnnotation(clazz, DesiredAnnotation.class)
if (m == null) log("Nor the class, or any superclass have the desired annotation")
else {
    m.setAccessitble(true);
    m.invoke(obj, arguments);
}

注意事项:

  • 这不包括接口,如果您需要覆盖接口,请检查getInterfaces()(此方法按声明顺序返回接口)。
  • 如果某个班级A有一个覆盖方法desiredMethod,没有注释,并且扩展了一个类SuperA,则会有一个方法desiredMethod,带有所需的注释,返回SuperA#desiredMethod,但是当你调用它时,它将在A类中调用(就像正常的调用一样)

答案 1 :(得分:0)

  

我的问题是可能有一些方法受到保护,私有等等。我想忽略这些修饰符并获得对所有方法的访问权(即使它是私有等)。

你需要在调用它之前调用Method.setAccessible(true),而不是忘记在finally块中恢复其原始值。