web-dev-qa-db-ja.com

Javaでのクラス型の比較

Javaのクラスタイプを比較したい。

私はこれができると思った:

class MyObject_1 {}
class MyObject_2 extends MyObject_1 {}

public boolean function(MyObject_1 obj) {
   if(obj.getClass() == MyObject_2.class) System.out.println("true");
}

関数に渡されたobjがMyObject_1から拡張されたかどうかを比較したかったのです。しかし、これは機能しません。 getClass()メソッドと.classは異なるタイプの情報を提供するようです。

クラスタイプを比較するためだけに別のダミーオブジェクトを作成せずに、2つのクラスタイプを比較するにはどうすればよいですか?

45
Carven

これを試して:

MyObject obj = new MyObject();
if(obj instanceof MyObject){System.out.println("true");} //true

継承のため、これはインターフェイスにも有効です。

class Animal {}
class Dog extends Animal {}    

Dog obj = new Dog();
Animal animal = new Dog();
if(obj instanceof Animal){System.out.println("true");} //true
if(animal instanceof Animal){System.out.println("true");} //true
if(animal instanceof Dog){System.out.println("true");} //true

Instanceofの詳細については、 http://mindprod.com/jgloss/instanceof.html

48
Thor

instanceofを使用したくない、または使用できない場合は、equalsと比較してください。

 if(obj.getClass().equals(MyObject.class)) System.out.println("true");

ところで-少なくともサンプルコードでは、ステートメントの2つのClassインスタンスは実際には同じである必要があるため、奇妙です。それらはmay以下の場合に異なります:

  • クラスの名前は同じですが、異なるパッケージで定義されています
  • クラスのフルネームは同じですが、異なるクラスローダーによってロードされます。
30
Andreas_D

私のマシンでtrueを出力します。それ以外の場合は、Javaで何も期待どおりに動作しません。これはJLSで説明されています: 4.3.4参照型が同じ場合

複数のクラスローダーが配置されていますか?


ああ、このコメントに応えて:

私の質問にタイプミスがあることに気付きました。私はこのようにする必要があります:

MyImplementedObject obj = new MyImplementedObject ();
if(obj.getClass() == MyObjectInterface.class) System.out.println("true");

MyImplementedObjectはMyObjectInterfaceを実装しています。つまり、実装されたオブジェクトと比較しています。

確認できる場合は、次のいずれかを実行できます。

if(MyObjectInterface.class.isAssignableFrom(obj.getClass()))

またははるかに簡潔

if(obj instanceof MyobjectInterface)
10

前述のように、2つの異なるクラスローダーに同じクラスをロードしない限り、コードは機能します。これは、メモリ内に同じクラスの複数のバージョンが同時に必要な場合や、オンザフライのコンパイル処理(私と同じように)を行っている場合に発生する可能性があります。

この場合、これらを同じクラスと見なしたい場合(ケースによっては妥当かもしれません)、名前を一致させて比較できます。

public static boolean areClassesQuiteTheSame(Class<?> c1, Class<?> c2) {
  // TODO handle nulls maybe?
  return c1.getCanonicalName().equals(c2.getCanonicalName());
}

この比較は、クラス名を比較することと同じことを行うことに注意してください。クラスの1つのバージョンから別のバージョンにキャストできるとは思わないので、リフレクションを検討する前に、クラスローダーの混乱の正当な理由があることを確認する必要があります。

3
djjeck

Equals()のClass.Javaソースコードを確認します。

public boolean equals(Object obj) {
return (this == obj);
}
0
Li Tao

instanceOfまたは...を使用してオブジェクトをクラスと比較することは既に回答済みです。

2つのオブジェクトがあり、それらのタイプをお互いと比較したい場合、以下を使用できます。

if (obj1.getClass() == obj2.getClass()) {
   // Both have the same type
}
0
Mahdi-Malv

うーん... Classはequals()を実装する場合としない場合があることに注意してください。これは仕様では必要ありません。たとえば、HP FortifyはmyClass.equals(myOtherClass)にフラグを立てます。

0
Max Tardiveau