web-dev-qa-db-fra.com

Comparaison des types de classe en Java

Je veux comparer le type de classe en Java.

Je pensais pouvoir faire ceci:

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");
}

Je voulais comparer au cas où l'obj transmis à la fonction était étendu à partir de MyObject_1 ou non . Il semble que la méthode getClass () et la classe .class donnent un type d'information différent.

Comment comparer deux types de classe sans avoir à créer un autre objet factice pour comparer le type de classe?

39
Carven

Essaye ça:

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

En raison de l'héritage, ceci est également valable pour les interfaces:

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

Pour en savoir plus sur instanceof: http://mindprod.com/jgloss/instanceof.html

44
Thor

Si vous ne voulez pas ou ne pouvez pas utiliser instanceof, comparez avec equals:

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

BTW - c'est étrange, car les deux instances Class de votre déclaration devraient être identiques, du moins dans votre exemple de code. Ils peuvent être différents si:

  • les classes ont le même nom abrégé mais sont définies dans des packages différents
  • les classes ont le même nom complet mais sont chargées par des chargeurs de classes différents.
28
Andreas_D

Il imprime true sur ma machine. Et ce devrait être le cas, sinon rien en Java ne fonctionnerait comme prévu. (Ceci est expliqué dans le JLS: 4.3.4 Quand les types de référence sont identiques )

Avez-vous plusieurs chargeurs de classe en place?


Ah, et en réponse à ce commentaire:

Je me rends compte que j'ai une faute de frappe dans mon question. Je devrais être comme ça:

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

MyImplementedObject implémente MyObjectInterface Donc, en d'autres termes, je Je le compare avec son implémenté objets.

OK, si vous voulez vérifier que vous pouvez faire soit:

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

ou beaucoup plus concis

if(obj instanceof MyobjectInterface)
9

Comme indiqué précédemment, votre code fonctionnera à moins que les mêmes classes ne soient chargées sur deux chargeurs de classes différents . Cela peut arriver si vous avez besoin de plusieurs versions de la même classe en mémoire en même temps, ou si vous faites des choses étranges sur la compilation des trucs (comme je suis).

Dans ce cas, si vous souhaitez les considérer comme appartenant à la même classe (ce qui peut être raisonnable selon les cas), vous pouvez faire correspondre leurs noms pour les comparer.

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

Gardez à l'esprit que cette comparaison fera exactement ce qu'elle fait: comparer les noms de classe; Je ne pense pas que vous serez en mesure de passer d’une version d’une classe à l’autre et, avant de vous pencher sur la réflexion, vous voudrez peut-être vous assurer qu’il ya une bonne raison pour le désordre de votre chargeur de classe.

3
djjeck

Vérifiez le code source de Class.Java pour equals ()

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

Hmmm ... Gardez à l'esprit que Class peut ou non implémenter equals () - ce n'est pas requis par la spécification Par exemple, HP Fortify marquera myClass.equals (myOtherClass).

0
Max Tardiveau