instanceofとgetClass()


114

getClass()and ==operator over instanceOfoperator を使用すると、パフォーマンスが向上します。

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

どちらのガイドラインを使用getClass()するのinstanceOfですか?

シナリオを考える:私は一致する正確なクラスを知っている、あるStringInteger(これらは、最終的なクラスである)、など

instanceOfオペレーターの悪い習慣を使用していますか?


3
これは、stackoverflow.com / questions / 596462 / …で説明されています。
クレメントP

2
タイミングメソッドが人為的な遅延を引き起こし、不正なタイミング結果を生成しています。チェックを行う順序を入れ替えると、最初に行うチェック(==またはinstanceof)が常に長くなります。私はそれがprintln()sだと思います。あなたはあなたのタイミングブロックにそのようなものを決して含めるべきではありません。
kurtzmarc 2012

コメントを1つだけ離して、パフォーマンスを比較するには、精度を向上させるために複数のサイクル反復(例:10000)を使用します。1回の呼び出しだけでは十分ではありません。
martins.tuga 14年

回答:


140

パフォーマンスという理由instanceofとはgetClass() == ...異なっているが、彼らは別のことをやっているということです。

  • instanceof左側のオブジェクト参照(LHS)が右側のタイプのインスタンス(RHS)であるか、サブタイプであるかをテストします。

  • getClass() == ... 型が同一かどうかをテストします。

したがって、パフォーマンスの問題を無視し、必要な答えを提供する代替手段を使用することをお勧めします。

instanceOfオペレーターの悪い習慣を使用していますか?

必ずしも。いずれかの過剰使用instanceOfまたはgetClass() かもしれ「デザインのにおい」。注意しないと、新しいサブクラスを追加するとかなりの量のコードが再処理される設計になってしまいます。ほとんどの場合、推奨されるアプローチは、ポリモーフィズムを使用することです。

ただし、「デザインのにおい」ではない場合があります。たとえばequals(Object)、引数の実際の型をテストし、false一致しない場合は返す必要があります。これは、を使用して行うのが最適getClass()です。


「ベストプラクティス」、「バッドプラクティス」、「デザインの匂い」、「アンチパターン」などの用語は控えめに使用し、疑いを持って扱う必要があります。彼らは白黒の考え方を奨励します。純粋にドグマに基づくのではなく、状況に応じて判断することをお勧めします。たとえば、誰かが言ったものは「ベストプラクティス」です。


@StephenCあなたが言ったように、code smellどちらかを使用することです。つまり、どちらかを使用するのは、悪いデザイン(非多態)コードの結果です。これらのどちらかの使用法をこのように推測できますか?
2014年

@overexchange-1)「使用」ではなく「使用」と言いました。2)それとは別に、私はあなたが何を求めているのか理解できません。「使用法を推測...」とはどういう意味ですか??? コードはこれらのものを使用するか、使用しません。
Stephen C

instanceof&の使用はgetClass()、コードの既存の悪い設計(非ポリモーフィック)が原因で発生すると推測します。私は正しいですか?
2014年

5
@overexchange- instanceof(たとえば)のすべての使用が悪い設計であることを正当に推測することはできません。それが最善の解決策であるかもしれない状況があります。も同じですgetClass()。私は「使いすぎ」ではなく使いすぎ」と言ったことを繰り返します。根拠のない独断的なルールを盲目的に適用するのではなく、すべてのケースをそのメリットで判断する必要があります。
スティーブンC

44

クラスを正確に照合しますか?たとえばFileInputStream、サブクラスの代わりにのみ照合しFileInputStreamますか?その場合は、およびを使用getClass()してください==。私は通常、equalsでこれを行うので、XのインスタンスがXのサブクラスのインスタンスと等しいとは見なされません。一方、2つのオブジェクトが同じであることを比較するには、通常、この方法が便利です。 1つの特定のクラスよりもクラスのもので。

それ以外の場合は、を使用しますinstanceof。することを注意getClass()あなたがで開始するnull以外の参照を持っている、またはあなたが買ってあげるようにする必要がありますNullPointerException一方で、instanceof意志だけで復帰false最初のオペランドがnullの場合。

個人的には私instanceofはもっと慣用的だと思います-しかし、それらのどちらかを広範囲に使用することは、ほとんどの場合デザインのにおいです。


18

これが尋ねられてからしばらく経ちましたが、昨日代替案を学びました

私たちは皆あなたができることを知っています:

if(o instanceof String) {   // etc

しかし、クラスのタイプが正確にわからない場合はどうすればよいでしょうか。一般的にはできません:

if(o instanceof <Class variable>.getClass()) {   

コンパイルエラーが発生するためです。
代わりに、ここに代替があります-isAssignableFrom()

例えば:

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}

8
使用しないでくださいisAssignableFromo instanceof Stringリフレクションを使用して記述する正しい方法はString.getClass().isInstance(o)です。javadocは次のようにも述べています。このメソッドは、Java言語instanceof演算子の動的な同等物です。
Andreas

3

getClass()には、以下のコードの出力に示されているように、オブジェクトが同じクラス、同じランタイムタイプの他のオブジェクトとのみ等しいという制限があります。

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
        }
    }
}

出力:

SubClassはParentClassを拡張します。subClassInstanceはinstanceof ParentClassです。

異なるgetClass()は、subClassInstanceとparentClassInstanceで結果を返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.