web-dev-qa-db-ja.com

Java isInstance vs instanceOf演算子

ジェネリックス全体がループのために私をちょっと投げている、そしてさらにRTT。

特定ですか?ああ、ここに要点があります。

enum QueryHelper {
  query1,
  query2;
  static <T> QueryHelper getQueryHelper (Class<T> expectedReturn) {
    if (expectedReturn.isInstance (SomeRelatedClass.class))
      return query1;
    else
      return query2;
  }
}

そして、私はそれを次のように呼びます:

...
QueryHelper helper = QueryHelper.getQueryHelper(SomeRelatedClass.class);
...

これは、実際のヘルパーでクエリの戻り値の型を本当に柔軟に割り当てることができるようにするためです。それはいくつかのキャストとオブジェクトの作成を行います。私が見ているのは、一致がないということです。これを他の方法で行うべきですか?それともアイデア全体が悪いのですか?

そして、これの本当の核心は、class.isInstanceとinstanceOf演算子の違いを理解していないことです。後者を使用する必要がありますか?

25
rybit

これは、実際のヘルパーでクエリの戻り値の型を本当に柔軟に割り当てることができるようにするためです。

このメソッドの戻り値の型に柔軟性はありません

static <T> QueryHelper getQueryHelper (Class<T> expectedReturn) {
    if (expectedReturn.isInstance (SomeRelatedClass.class))
      return query1;
    else
      return query2;
}

常にQueryHelperのインスタンスを返します。戻り値の型を柔軟にしたい場合は、次のように定義する必要があります。

static <T> T getQueryHelper (Class<T> expectedReturn) {
}

引数の型に依存するため、戻り値の型は柔軟になりました

そして、これの本当の核心は、class.isInstanceとinstanceOf演算子の違いを理解していないことです。

違いは、instanceofがコンパイル時に修正される型チェックを実行することです。次に例を示します。

static boolean isInstance(Object myVar) {
    return (myVar instanceof Foo);
}

myVarがFooのインスタンスであることを常に確認しますが、

static <T> boolean isInstance(Object myVar, Class<T> expectedType) {
    return expectedType.isInstance(myVar);
}

myVarがexpectedTypeのインスタンスであることを確認しますが、メソッドが呼び出されるたびにexpectedTypeは異なるタイプになる可能性があります

30
Dónal

Class.isInstance()は、コードが期待するように機能しません。渡したオブジェクトがクラスのインスタンスかどうかをテストします。あなたのコードでは:

expectedReturn.isInstance(SomeRelatedClass.class)

渡したオブジェクトはClassオブジェクトです。代わりにこれを試してください。これはtrueを返します。

Class.class.isInstance(SomeRelatedClass.class);

あなたがおそらく探しているのは Class.isAssignableFrom() です、例えば:

Object.class.isAssignableFrom(Class.class);

これができることを意味します:

Class klass = ...;
Object o = klass;
3
vanza

IsInstanceの期待される引数は、クラスオブジェクトが表すクラスのインスタンスである可能性があるオブジェクトです。比較しているのはクラスのインスタンスです... Java.lang.Class!したがって、一致しません。

たとえば、次のようになります。

Class.class.isInstance(SomeRelatedClass.class);

また、本当です(この方法で実際にクエリヘルパーを構築することの正気さに関するアーキテクチャの解説なし)

expectedReturn.isInstance(new SomeRelatedClass());
1
Affe