オブジェクトのクラスを決定する方法は?


510

クラスBとクラスがクラスをC拡張しAていて、タイプBまたはのオブジェクトCがある場合、それがインスタンスであるタイプをどのように判別できますか?


14
最初に思い浮かぶのは、@ starblueキャスティングです。私は疑うinstanceofは、それの必要がなかった場合は、オペレータが存在するであろう。
b1nary.atr0phy 2012

@ b1nary.atr0phyは、最初にisntanceof演算子を使用するのは適切ではありません。互換性のない型へのキャストがあれば、私はClassCastExceptionが発生につながると信じて
committedandroider

回答:


801
if (obj instanceof C) {
//your code
}

31
オブジェクトがクラスのインスタンスでない場合、それは逆の小切手またはどうかを確認する方法を注意することは有益である:if(!(obj instanceof C))
Dzhuneyt

32
getClass()メソッドが元の質問に対する答えだと思います。この場合(obj instanceof A)も「true」出力を提供しますが、その目的は、オブジェクトのランタイムクラスを画像から見つけることです。Parent1がChild1とChild2によって拡張されている場合は、次のcode Child1 child1 = new Child1();を試してください。Parent1 parentChild = new Child2(); Child2 child2 = new Child2(); (child1 instanceof Parent1); (child1 instanceof Child1); (parentChild instanceof Child2); (parentChild instanceof Parent1); (parentChild instanceof Child1); code 、instanceofの意図をクリアするかもしれません。
Bhavesh Agarwal

間違いなくインターフェースを構築するための代替案
JohnMerlino '6/07/14

3
単一のインターフェースを実装する2つのクラスがある場合はどうなりますか?オブジェクトの正確なクラスを区別するにはどうすればよいですか?
olyv

3
ただし、objがnullの場合は機能しません。ソリューションは、ParentInterface.class.isAssignableFrom(Child.class)になります
alexbt


178

複数の正解が提示されましたが、さらに多くのメソッドがあります。Class.isAssignableFrom()単にオブジェクトをキャストしようとしています(これにより、がスローされる場合がありますClassCastException)。

可能な方法の要約

オブジェクトobjがタイプのインスタンスであるかどうかをテストする可能な方法を要約しましょうC

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

null取り扱いの違い

nullただし、処理には違いがあります。

  • 最初の2つのメソッドでは、式はfalseif objis nullnullis of何かのインスタンスではない)と評価されます。
  • 3番目のメソッドはNullPointerException明らかにスローします。
  • 逆に4番目と5番目のメソッドは、どのタイプにもキャストできるnullため受け入れnullます!

覚えておいてください:null どのタイプのインスタンスでもありませんが、どのタイプにもキャストできます

ノート

  • Class.getName()オブジェクトがタイプではなくそのサブクラスである場合、「is-instance-of」テストの実行に使用しないでください。オブジェクトのC名前とパッケージが完全に異なる可能性があります(したがって、クラス名は明らかに一致しません)。まだタイプCです。
  • 同じ継承の理由Class.isAssignableFrom()対称ではありません:のタイプがのサブクラスである場合に
    obj.getClass().isAssignableFrom(C.class)返されます。falseobjC

6
これは、さまざまな方法の多くの落とし穴の本当に素晴らしい要約です。そのような完全な書き込みをありがとう!
ケルシン

32

以下を使用できます。

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH。しかし、ほとんどの場合、それを制御フローまたは同様のものに使用することは良い習慣ではないと思います...


私はそれを使用して汎用ロガーを作成したので、オブジェクトをロガーに送信し、ログタグやログ文字列を毎回与えるのではなく、オブジェクトのクラス名に応じてログに記録しました。ありがとう
MBH 2016

24

提案された方法のいずれかの使用は、悪いOO設計に基づいたコードのにおいと見なされます。

あなたのデザインが良ければ、あなたは自分自身を使用しgetClass()たり、instanceof

提案された方法のいずれでも機能しますが、デザイン的には、覚えておくべきことだけです。


3
ええ、おそらくgetClassとinstanceofの使用の99%は、ポリモーフィックなメソッド呼び出しで回避できます。
リザードを請求する

3
私は同意します。この場合、私は所有権のない不十分に設計されたスキーマに従ってxmlから生成されたオブジェクトを操作しています。
運送業者

28
本質的にではない。インターフェースの分離が良い場合もあります。AがBであるかどうかを知りたいが、AがBであることを必須にしたくない場合があります。ほとんどの機能に必要なのはAだけです。Bにはオプションの機能があります。
MetroidFan2002 2009

8
また、オブジェクトが比較対象のクラスと同じであることを確認する必要がある場合もあります。たとえば、私は自分のクラスを作成するときにObjectのequalsメソッドをオーバーライドするのが好きです。入ってくるオブジェクトが同じクラスであることを常に確認します。
StackOverflowed '25年

58
また、理由を正確に説明せずに何か悪いことを人々に伝えることや、問題が説明されている紙、本、またはその他のリソースへの参照を与えることは建設的ではないと見なされます。したがって、私がStackOverflowにいることを知っているのに、なぜ人々がこの回答にそれほど賛成したのかわかりません。何かが...ここに変化している
アドリアン・ペレス

15

この場合、リフレクションを使用できます

objectName.getClass().getName();

例:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

この場合、オブジェクトがHttpServletRequestインターフェース参照変数に渡すクラスの名前を取得します。


これは正しいです。only obj.getClass()を使用すると、className、prefixexという単語が返されますclass
x6iae

request.getClass().getName();すべてのパッケージを印刷します!クラス名とともに
shareef

13

.isInstance" Class"クラスにはメソッドもあります。オブジェクトのクラスを経由して取得したmyBanana.getClass()場合、オブジェクトmyApplemyBanana経由と同じクラスのインスタンスであるかどうかを確認できます

myBanana.getClass().isInstance(myApple)

1

isinstance()実行時に知りたい場合は、でのチェックだけでは不十分です。使用する:

if(someObject.getClass().equals(C.class){
    // do something
}

0

GeneralUtilsクラスでブロー関数を使用し、それが役立つかどうかを確認します

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}

0

スイッチケースを使用する必要はなく、Java 8ジェネリックを使用して実行時にオブジェクトインスタンスを取得しました

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

任意のタイプのデータを渡すと、メソッドは、呼び出し中に渡したデータのタイプを出力します。例えば

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

以下は出力です

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.