9

私は現在、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のマップを維持する以外に、この問題に対処する別の方法があるかどうか疑問に思っています。(これは現在行われているので、これは学習のためです)

ボクシングとタイプ情報の動作は、ここでは一貫していないようです。

誰かがこれに光を当てることができますか?

4

1 に答える 1

10

リフレクションによると、オブジェクト (int.class) の戻り値の型は Number.class に割り当てられませんが、メソッドの呼び出しを続行すると、実際に Integer.class を取得できますか?

絶対。リフレクション API はおそらく実際の を返すことができないintため、値をInteger. 他に何ができるでしょうか?

ボックスにする必要があるという事実は、割り当て可能性を からに変更しませ次のドキュメントを参照してください。intNumberisAssignableFrom

この Class オブジェクトがプリミティブ型を表す場合、指定された Class パラメータがまさにこの Class オブジェクトであれば、このメソッドは true を返します。それ以外の場合は false を返します。

したがって、ドキュメントに従って正確に動作しています。

int -> Integer、Integer -> Integer、float -> Float、Float -> Float のマップを維持する以外に、この問題に対処する別の方法があるかどうか疑問に思っています。(これは現在行われているので、これは学習のためです)

ええ、それは私には正しいように聞こえます。またはSet<Class>、明示的にマッピングするのではなく、単にプリミティブな数値型を使用します。

于 2012-08-01T17:50:57.900 に答える