私は現在、OSGiシステムでメトリックを収集するための小さなフレームワークに取り組んでいます。その中核となるのはアノテーション@Metricであり、サービスの特定のメソッドが要求されたときにメトリック(数値など)を提供できることを示します。
これらのメソッドは次のようになります。
@Metric
public int getQueueSize() {...}
また
@Metric
public double getAvgTaskTime() {...}
リフレクションを使用して、サービス実装クラスを検査し、。で注釈が付けられたメソッドを登録しています@Metric
。健全性チェックとして、メソッドが実際に数値を提供することを確認しています。私はこれを試しましたが失敗しました:
for (Method method: metricSource.getClass().getMethods()) {
if (method.isAnnotationPresent(Metric.class) && Number.class.isAssignableFrom(method.getReturnType()) {
// add method for later process
}
次に、後でプロセッサで次のことを行います。
Number value = (Number) method.invoke(target, obj[]);
プリミティブ型の場合、たとえばint.class
、それはNumber.classに割り当てられませんが、ボックス化された型Integer.classは割り当てられます。くそ。進む。
次にMap<Class<?>, Extractor>
、Extractorがクラスを取得し、そのクラスにパラメーターをキャストする場所を作成しました。
public NumberExtractor(Class<? extends Number> clazz) {
this.clazz = clazz;
}
public double extract(Object val) {
Number nbr = clazz.cast(val);
return nbr.doubleValue();
}
}
以前の観察に直面して、私は次のようなエントリを追加しました:
extractorMap.put(int.class, new NumberExtractor(int.class));
しかし、それもうまくいきませんでした。Integer.classをintにキャストできなかったというランタイムクラスキャスト例外が発生しました。コンパイラはに文句を言わずnew NumberExtractor(int.class)
、境界チェックClass<? extends Number>
を通過させることにも注意してくださいint.class
最後に、この組み合わせは機能しました:
extractorMap.put(int.class, new NumberExtractor(Integer.class));
ここで何が起こっているのですか?リフレクションによると、オブジェクトの戻り型(int.class)はNumber.classに割り当てられませんが、invokeメソッドを続行すると、実際にはInteger.classを取得しますか?WhiskyTangoFoxtrot ?!
int-> Integer、Integer-> Integer、float-> Float、Float-> Floatのマップを維持する以外に、この問題に対処する別の方法があるかどうか疑問に思っています。(これは現在行われているので、これは学習のためです)
ボクシングとタイプ情報の動作は、ここでは一貫していないようです。
誰かがこれに光を当てることができますか?