2015-04-23 40 views
2

我目前正在制作一个库,这是一个工具,用于处理与问题无关的东西(我隐含地不说这个主题,因为它不是很重要),但是它确实使用反射。在不同的对象上做同样的事情

我正在从类中检索所有声明和继承的方法,它目前正常工作并且不是问题。但是,事情是,我也需要为子类做这个,因为这些子类继承了类似的方法(但是你不能重写那些方法)。

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

通常我会寻找一个共享的超类,但在这种情况下,我更喜欢拥有Class []和Method []。对于初学者来说,我做了一些研究,发现了一些共同的超类:

  • GenericDeclaration
  • AnnotatedElement中

因为我需要两个类[]和方法[]数组我想到的东西 像泛型,所以该方法看起来像:

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 
} 

现在这使你不必手动施放的所有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在一个循环中,所以我不能拉班但是,你可以。 希望这可以帮助未来的人:)再次感谢@dasblinkenlight的灵感!

+1

“可是我怎么会发现我是否需要调用getDeclaredMethods或getDeclaredClasses”你的API的输入是什么驱动决定调用其中一个? 'getT'没有参数,它也是'static',所以它怎么知道要调用什么? – dasblinkenlight

+0

@dasblinkenlight这是一个很好的观点..那么一个方法,可以采取一个枚举作为参数,以确定是否需要获得类或方法?这将是一些三元操作,但是如果我使用超类,它应该可以工作,但是在代码中它看起来不像我想要的那样干净。 – engineercoding

回答

1

你的getT需要得到一些输入,以决定做什么。

那么一个方法可以采取enum作为参数来确定它是否需要获取类或方法呢? (从评论

有一种更好的方法:定义执行适当的提取的接口,并且使这两个实例 - 一个用于提取的类,和一个用于提取方法:

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采取的“提取”,像这样:

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); 
+0

非常感谢你为这个天才的想法!这种问题很容易明显解决,你只需要在盒子外面思考,多用些语言。谢谢!! – engineercoding

相关问题