Vergleich von Klassentypen in Java

Lesezeit: 5 Minuten

Carvens Benutzeravatar
Schnitzen

Ich möchte den Klassentyp in Java vergleichen.

Ich dachte, ich könnte das tun:

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

Ich wollte vergleichen, ob das an die Funktion übergebene Objekt von MyObject_1 erweitert wurde oder nicht. Aber das funktioniert nicht. Es scheint, als ob die Methode getClass() und die .class unterschiedliche Arten von Informationen liefern.

Wie kann ich zwei Klassentypen vergleichen, ohne ein weiteres Dummy-Objekt erstellen zu müssen, nur um den Klassentyp zu vergleichen?

  • Diese Frage ist verwirrend und hat mich in die Irre geführt, wie “==” beim Vergleich von Klassen/Schnittstellen funktioniert. Das Beispiel sollte in sich abgeschlossen sein. Was Sie an Ihre Funktion übergeben, sollte im Beispiel stehen!

    – crof

    2. Januar 2017 um 13:35 Uhr

Benutzeravatar von Thor
Thor

Versuche dies:

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

Aufgrund der Vererbung gilt dies auch für Schnittstellen:

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

Zum Weiterlesen auf instanceof: http://mindprod.com/jgloss/instanceof.html

  • Aber was passiert, wenn ich überprüfen möchte, ob ein Tier eine Instanz von Hund ist? Ist es noch möglich? Sprich: public void check(Animal obj) { if(obj instanceof Dog){System.out.println(“true”);} } Ist das noch möglich?

    – Schnitzen

    27. Mai 2011 um 8:50 Uhr


  • @xEnON: Dies ist möglich, wird aber immer false zurückgeben. Sie können nicht prüfen, ob ein Interface eine Instanz einer konkreten Klasse ist.

    – Thor

    27. Mai 2011 um 8:56 Uhr

  • Wenn ich also eine Funktion habe, die diese Polymorphismusfunktion nutzt, kann ich ihren genauen Klassentyp zur Laufzeit nicht überprüfen?

    – Schnitzen

    27. Mai 2011 um 9:00 Uhr

  • Entschuldigung, es ist falsch, dass dies immer falsch zurückgibt. Habe deinen Kommentar nicht aufmerksam genug gelesen. Siehe meine Antwort.

    – Thor

    27. Mai 2011 um 9:04 Uhr


  • Oh … Ich verstehe, dass es falsch ist und wird falsch zurückgeben. Ich dachte nur, ob es einen anderen Weg gibt, dieses Ziel zu erreichen.

    – Schnitzen

    27. Mai 2011 um 9:12 Uhr

Wenn Sie nicht verwenden möchten oder können instanceofdann vergleiche mit equals:

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

Übrigens – es ist seltsam, weil die beiden Class Instanzen in Ihrer Anweisung sollten wirklich gleich sein, zumindest in Ihrem Beispielcode. Sie kann anders sein, wenn:

  • die Klassen haben denselben Kurznamen, sind aber in unterschiedlichen Paketen definiert
  • Die Klassen haben den gleichen vollständigen Namen, werden aber von unterschiedlichen Classloadern geladen.

  • Ich frage mich, warum diese Antwort so viele Upvotes hat (ich denke, einer der Gründe ist, dass die Frage geändert wurde, nachdem diese Antwort gepostet wurde)? java.lang.Class überschreibt nicht Object.equalswas bedeutet, dass für zwei Nicht-Null cls1 und cls2: cls1.equals(cls2) ist genau dann wahr, wenn cls1 == cls2 ist wahr. Das bedeutet, dass der vorgeschlagene Ansatz derselbe ist, den der Themenstarter beschrieben hat.

    – Valentin Kowalenko

    10. Februar 2019 um 1:06 Uhr

Benutzeravatar von Sean Patrick Floyd
Sean Patrick Floyd

Es druckt true auf meiner Maschine. Und das sollte es auch, sonst würde in Java nichts wie erwartet funktionieren. (Dies wird im JLS erklärt: 4.3.4 Wenn Referenztypen gleich sind)

Sind mehrere Classloader vorhanden?


Ah, und als Antwort auf diesen Kommentar:

Mir ist klar, dass ich einen Tippfehler in meiner Frage habe. Ich sollte so sein:

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

MyImplementedObject implementiert MyObjectInterface. Mit anderen Worten, ich vergleiche es mit seinen implementierten Objekten.

OK, wenn Sie überprüfen möchten, ob Sie Folgendes tun können:

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

oder die viel prägnanter

if(obj instanceof MyobjectInterface)

  • Mir ist klar, dass ich einen Tippfehler in meiner Frage habe. Ich sollte so sein: MyImplementedObject obj = new MyImplementedObject (); if(obj.getClass() == MyObjectInterface .class) System.out.println(“true”); MyImplementedObject implementiert MyObjectInterface. Mit anderen Worten, ich vergleiche es mit seinen implementierten Objekten.

    – Schnitzen

    27. Mai 2011 um 8:33 Uhr


  • Ich habe meinen Beitrag mit dem richtigen Code aktualisiert, den ich meinte. Sorry für die Verwirrung.

    – Schnitzen

    27. Mai 2011 um 8:40 Uhr

  • Danke!! Da obj in Ihrem Update von MyObjectInterface erweitert wird, ist der Vergleich von obj mit MyObjectInterface möglicherweise immer noch in Ordnung. Aber was passiert, wenn ich in die entgegengesetzte Richtung vergleichen wollte. Wenn beispielsweise obj MyObject_1 ist. Und es gibt ein MyObject_2, das von MyObject_1 erweitert wurde. Dann wollte ich prüfen, ob obj tatsächlich von MyObject_2 ist oder nicht, würde das noch funktionieren? Dies ist das Update in meinem Fragebeitrag.

    – Schnitzen

    27. Mai 2011 um 8:48 Uhr

Wie bereits erwähnt, funktioniert Ihr Code, es sei denn, Sie haben dieselben Klassen auf zwei verschiedene Klassenladeprogramme geladen. Dies kann passieren, wenn Sie mehrere Versionen derselben Klasse gleichzeitig im Speicher benötigen oder wenn Sie (so wie ich) seltsame Kompilierungs-Sachen im laufenden Betrieb machen.

Wenn Sie diese in diesem Fall als dieselbe Klasse betrachten möchten (was je nach Fall sinnvoll sein kann), können Sie ihre Namen vergleichen, um sie zu vergleichen.

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

Denken Sie daran, dass dieser Vergleich genau das tut, was er tut: Klassennamen vergleichen; Ich glaube nicht, dass Sie in der Lage sein werden, von einer Version einer Klasse in die andere umzuwandeln, und bevor Sie sich mit der Reflexion befassen, sollten Sie sicherstellen, dass es einen guten Grund für Ihr Classloader-Chaos gibt.

Vergleichen eines Objekts mit einer Klasse mit instanceOf oder … ist bereits beantwortet.

Wenn Sie zwei Objekte haben und deren Typen vergleichen möchten gegenseitigkönnen Sie verwenden:

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

Sams Benutzeravatar
Sam

Wenn Sie zwei Strings hätten und sie mit == vergleichen würden, indem Sie die Methode getClass() für sie aufrufen, würde sie true zurückgeben. Was Sie erhalten, ist eine Referenz auf dasselbe Objekt.

Dies liegt daran, dass es sich bei beiden um Referenzen auf dasselbe Klassenobjekt handelt. Dies gilt für alle Klassen in einer Java-Anwendung. Java lädt die Klasse nur einmal, sodass Sie zu einem bestimmten Zeitpunkt nur eine Instanz einer bestimmten Klasse haben.

String hello  = "Hello";
String world = "world";

if (hello.getClass() == world.getClass()) {
    System.out.println("true");
} // prints true

Benutzeravatar von Max Tardiveau
Max Tardiveau

Hmmm … Denken Sie daran, dass Class equals() implementieren kann oder nicht – dies ist in der Spezifikation nicht erforderlich. Beispielsweise kennzeichnet HP Fortify myClass.equals(myOtherClass).

1431150cookie-checkVergleich von Klassentypen in Java

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy