2

私は一般的に拡張に反対します。なぜなら、それはクラス間の非常に強いつながりを生み出し、それは偶然に壊れやすいからです。

しかし、私はついにそれの合理的なケースを見つけたと思いました-私はオプションで既存のシステムでファイルタイプの圧縮バージョンを使用したいと思います。圧縮されたバージョンは、圧縮されていないバージョンとほぼ同じ速さで、まったく同じメソッド(つまり、読み取りと書き込み)を使用できます。唯一の違いは、ディスク上の表現にあります。したがって、圧縮バージョンに非圧縮バージョンを拡張して、オプションで他のタイプをインサンティファイするだけで、どちらの種類のファイルも使用できるようにしました。

public class CompressedSpecialFile extends SpecialFile(){ ... }

if (useCompression){
    SpecialFile = new CompressedSpecialFile();
} else {
    SpecialFile = new SpecialFile();
}

ただし、プログラムの後の時点で、リフレクションを使用します。

Object[] values = new Object[]{SpecialFile sf, Integer param1, String param2, ...}
Class myclass = Class.forName(algorithmName);
Class[] classes = // created by calling .getClass on each object in values
constructor = myclass.getConstructor(classes); 
Algorithm = (Algorithm) constructor.newInstance(values)

これはすべて正常に機能しましたが、SpecialFileの実行時型がCompressedSpecialFileであるため、myclass.getConstructorクラスはNoSuchMethodExceptionをスローします。

ただし、これが拡張機能の動作方法だと思いました。CompressedSpecialFileはSpecialFileを拡張するため、SpecialFileを受け入れるパラメーターはすべてCompressedSpecialFileを受け入れる必要があります。これはJavaの反映の誤りですか、それとも私の理解の失敗ですか?

4

1 に答える 1

3

うーん、このバグレポートへの応答は、これが意図的なものであることを示しているようです。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4301875

互換性の理由から、この変更を行うことはできません。さらに、getConstructorはgetDeclaredMethodと同様に動作する必要があります。これも完全一致が必要であるため、一方を変更せずに他方を変更することは意味がありません。ただし、引数の型が一致する方法のみが異なるメソッドのスイートを追加することは可能です。実行時にリフレクション中に、コンパイラー、つまりデバッガーで静的に使用されるのと同じ過負荷解決アルゴリズムを適用したい場合が確かにあります。ただし、既存のAPIを使用してこの機能を実装することは難しくありません。そのため、この機能をコアリフレクションに追加するケースは弱いです。

そのバグレポートは、実装の詳細をもう少し提供する次のレポートの複製として閉じられました:http: //bugs.sun.com/bugdatabase/view_bug.do; jsessionid=1b08c721077da9fffffffff1e9a6465911b4e?bug_id=4287725

回避策getMethod
のユーザーは、引数に渡されたクラスを正確に識別する必要があります。

評価
この要求の本質は、ユーザーがClass.getMethodにコンパイラーと同じオーバーロードルールを適用することを望んでいることです。デバッガーやスクリプトインタープリターなどの特定の種類のリフレクティブプログラムで頻繁に発生する必要があるため、これは妥当な要求だと思います。すべての人が正しく理解できるように、標準の実装があると便利です。ただし、互換性のために、既存のClass.getMethodの動作はそのままにして、新しいメソッドを定義する必要があります。フットプリントに基づいてこの機能を除外する場合があります。これは、既存のAPIを使用して実装できるためですが、多少非効率的です。4401287も参照してください。リフレクションで過負荷の解決を提供する必要があるというコンセンサスがあるようです。
互換性の理由から、Class.get(Declared)+ {Method、Constructor}の実装は変更しないでください。新しい方法を導入する必要があります。これらのメソッドの仕様は、「一致」を定義するために変更する必要があります。バグ4651775を参照してください。

これらの参照されたバグと私が提供した実際のリンク(議論と可能な回避策がある場合)を掘り下げ続けることができますが、それは理由になっていると思います(Javaのoopをリフレクションに反映する新しいメソッドがまだ実装されていない理由は、 知らない)。

回避策の観点から、継承の1レベルの深さのバージョンでは、拡張クラスの名前である各クラスでgetSuperclass()を呼び出すことができると思いますが、それは非常にエレガントではなく、所定の方法で実装するクラス。非常に不器用です。ただし、別のオプションを探してみます。

于 2012-10-01T06:35:23.410 に答える