java - 配列 - object 型 判定 c#




Java汎用クラス-型を判別する (6)

.NETとは対照的に、Javaのジェネリックは「型消去」と呼ばれる手法によって実装されています。

つまり、コンパイラはクラスファイルを生成する際に型情報を使用しますが、この情報をバイトコードには転送しません。 javapまたは類似のツールを使用してコンパイルされたクラスを見ると、 List<String>は、Java-5以前のコードと同様に、クラスファイル内の単純なListObject )です。

ジェネリックListにアクセスするコードは、以前のバージョンで自分で作成しなければならないキャストを含めるために、コンパイラーによって「再書込み」されます。 実際には、次の2つのコードフラグメントは、コンパイラがそれらを使って完了すると、バイトコードパースペクティブと同じです。

Java 5:

List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);

Java 1.4以前:

List stringList = new ArrayList();
stringList.add("Hello World");
String hw = (String)stringList.get(0);

Java 5のジェネリッククラスから値を読み取るときには、宣言された型パラメータへの必要なキャストが自動的に挿入されます。 挿入時に、コンパイラは挿入しようとしている値をチェックし、文字列でない場合はエラーで中止します。

既存のライブラリを再コンパイルする必要なしに、古いライブラリと新しい生成されたコードを相互運用可能に保つために、すべてが行われました。 これは、ジェネリッククラスと非ジェネリッククラスが並んでいるが、自由に交換することができない.NETの方法よりも大きな利点です。

両方のアプローチには長所と短所がありますが、それはJavaでの方法です。

あなたの元の質問に戻るには:実行時に型情報を取得することはできません。なぜなら、コンパイラがその作業を終えると、それはもう存在しないからです。 これは確かにいくつかの点で限界があり、その周りにはクラスインスタンスをどこかに格納することに基づいたいくつかの不気味な方法がありますが、これは標準的な機能ではありません。

https://code.i-harness.com

ジェネリックであるようにJavaクラスを作成している場合は、次のようになります。

public class Foo<T>

どのようにしてそのクラスの内部的に判断することができますか?

public ???? Bar()
{
    //if its type 1
    //    do this
    //if its type 2
    //    do this
    //if its type 3
    //    do this
    //if its type 4
    //    do this
}

私はJava APIの周りを突き刺して、Reflectionのstuff、instanceof、getClass、.classなどで演奏しましたが、頭や尾を作ることはできません。 私は近くにいるように感じていて、いくつかのコールを組み合わせるだけでいいですが、短くしていきます。

具体的には、クラスが3つのタイプのうちの1つでインスタンス化されているかどうかを判断しようとしています。


型の消去のため、これを直接行う方法はありません。 しかし、あなたができることは、 Class<T>をコンストラクタに渡し、 Class<T>の中でそれを保持することです。 次に、あなたが許可する3つの可能なClassタイプに対してそれをチェックすることができます。

ただし、可能なタイプが3つしかない場合は、代わりにリファクタリングをenum型にすることを検討してください。


問題は、コンパイル時にGenericのもののほとんどが消えてしまうことです。

一般的な解決策の1つは、オブジェクトの作成中に型を保存することです。

javaのタイプ消去動作の簡単な紹介については、このページをお読みください


実際にはGenericクラスではなく、いくつかの実装が異なるインターフェイスが必要です。 しかし、あなたが実際の具体的な目標を述べていれば、それはもっと明確になるでしょう。


私はVisageに同意します。 ジェネリックスはコンパイル時の検証用であり、実行時の動的型付け用ではありません。 あなたが必要とするようなサウンドは、実際には単に工場のパターンです。 しかし、あなたの "これを行う"がインスタンス化でない場合、単純な列挙型はおそらく同様にうまくいくでしょう。 マイケルが言ったように、少し具体的な例があれば、より良い答えを得るでしょう。


私はいくつかのプロジェクトについてここで説明したことと同様の解決策を使用しており、非常に有用であることがわかりました。

http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/

それのjistは次のものを使用しています:

 public Class returnedClass() {
     ParameterizedType parameterizedType = (ParameterizedType)getClass()
                                                 .getGenericSuperclass();
     return (Class) parameterizedType.getActualTypeArguments()[0];
}




generics