在不同的对象上做同样的事情

Approach doing the same stuff on different objects

我目前正在制作一个库,它是一个实用程序,可以让我处理与问题无关的事情(我隐含地没有说主题,因为它并不重要),但是它确实使用了反射。

我正在从 class 中检索所有已声明和继承的方法,目前工作正常,不是问题所在。但问题是,我也需要为子 classes 执行此操作,因为那些继承了类似的方法(但是你不能覆盖那些类似的方法)。

我面临的问题是它将使用相同的算法但会有差异,而不是调用 clazz.getDeclaredMethods() 我需要调用 clazz.getMethods。最好的方法是什么,我也需要在方法签名中使用 return Class[] 和 Method[]。

通常我会寻找一个共享的 superclass,但在这种情况下我更喜欢相应地有 Class[] 和 Method[]。对于初学者,我做了一些研究并发现了一些共享的 superclasses:

Since I need both Class[] and Method[] arrays I am thinking something like generics, so the method would look like:

public static <T extends GenericDecleration> T[] getT () {

}

正如 dasblinkenlight 所提到的,这将不起作用,因为该方法不接受任何参数并且无法检查是否检索 Class 或 Method 对象。

但是我如何检测是否需要调用 getDeclaredMethodsgetDeclaredClasses

在不重复大量代码的情况下执行此操作的最佳方法是什么?我真的试图在这里解释自己,但如果仍然不清楚我在做什么,请随时提问!

非常感谢您!


经过一番折腾,我找到了一个完全符合我需求的解决方案。这是泛型和@dasblinkenlight 解决方案的组合,如下所示:

public interface DeclExtractor<T extends GenericDecleration> {
    public T[] extract (Class clazz);
    public Class<? extends T[]) getGenericClass ();

    DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
        @Override
        public Method[] extract (Class clazz) {
            return clazz.getDeclaredMethods();
        }

        @Override
        public Class<? extends Method[]> getGenericClass () {
            return Method[].class;
        }
    }

    // Same for Class
}

现在该方法也会 return 正确的类型,因此您不必手动将所有 GenericDeclaration 转换为原始对象类型。我的问题是我为它使用了一个集合而不是正确的数组:

public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
    T[] declaration = extractor.extract (clazz);
    //.. The algorithm..

    // Return an instance of a collection as array (I use a set in my implementation)
    final Object[] objects = myCollection.toArray();
    return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}

从技术上讲,您不需要界面中的 getGenericClass 方法,但我在循环中直接使用 extract,因此我无法提取其中的 class,但是,您能够。 希望这对以后的人有帮助 :) 再次感谢@dasblinkenlight 的启发!

您的 getT 需要获得一些意见才能决定要做什么。

What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)

有一个更好的方法:定义一个执行适当提取的接口,并创建它的两个实例 - 一个用于提取 类,一个用于提取方法:

public interface DeclExtractor {
    GenericDecleration[] extract(Class cl);
    final DeclExtractor forClasses = new DeclExtractor() {
        public GenericDecleration[] extract(Class cl) {
            // make an array of GenericDecleration from extracted classes
        }
    };
    final DeclExtractor forMethods = new DeclExtractor() {
        public GenericDecleration[] extract(Class cl) {
            // make an array of GenericDecleration from extracted methods
        }
    };
}

现在您可以重写 getT 以获取 "extractor",如下所示:

public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
    ...
    // When it's time to get components of the class, make this call:
    GenericDecleration[] components = extractor.extract(cl);
    ...
}

要发起对 getT 的调用,请传递 DeclExtractor.forClassesDeclExtractor.forMethods:

GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);