web-dev-qa-db-ja.com

instanceof対getClass()

instanceOf演算子よりもgetClass()および==演算子を使用すると、パフォーマンスが向上します。

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演算子を使用するのは悪い習慣ですか?

103
blob

instanceofgetClass() == ...のパフォーマンスが異なる理由は、それらが異なることをしているからです。

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

  • getClass() == ...は、タイプが同一であるかどうかをテストします。

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

そして、はい、どちらかを使いすぎると「デザインの匂い」になるかもしれません。注意を怠ると、新しいサブクラスを追加すると大量のコードが再設計されるという設計になります。ほとんどの場合、推奨されるアプローチはポリモーフィズムを使用することです。

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

129
Stephen C

質問されてからしばらく経ちましたが、昨日は別の方法を学びました

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

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())
}
18
Andy Dingfelder

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は、ParentClassのインスタンスです。

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

2
Saurav Sahu