2015-04-23 65 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

相關問題